ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 20140625 (메시지 큐 우선순위, 공유 메모리)
    부산IT학원/스마트컨트롤러 2014. 6. 25. 12:30

    88일차






    ----------------------

    메시지 큐 우선순위

    ----------------------



    --- 메시지가 처리될 때 우선순위를 정할 수도 있다.


    예제 소스)


    26_3.c


          1 #include <stdio.h>
          2 #include <string.h>
          3 #include <sys/types.h>
          4 #include <sys/ipc.h>
          5 #include <sys/msg.h>
          6
          7 #define SIZE 124
          8
          9 struct
         10 {
         11     long type;
         12     char data[SIZE];
         13 }msg_data;
         14
         15 int main()
         16 {
         17     int msqid;
         18     int data_len;
         19     char buffer[SIZE];
         20
         21     if((msqid = msgget((key_t)7878, IPC_CREAT |0666)) == -1)
         22     {
         23         perror("msgget failed");
         24         exit(1);
         25     }
         26
         27     while(1)
         28     {
         29         printf("input data => ");
         30         scanf("%s", buffer);
         31         fflush(stdin);
         32
         33         if(!strcmp(buffer, "quit"))
         34         {
         35             break;
         36         }
         37
         38
         39         printf("input priority -> ");
         40         scanf("%ld"&(msg_data.type));
         41         fflush(stdin);
         42         strcpy(msg_data.data, buffer);
         43
         44         if(msgsnd(msqid, &msg_data, strlen(msg_data.data), 0== -1)
         45         {
         46             perror("msgsnd failed");
         47             exit(1);
         48         }
         49     }
         50     return 0;
         51 }





    26_4.c


          1 #include <stdio.h>
          2 #include <sys/types.h>
          3 #include <sys/ipc.h>
          4 #include <sys/msg.h>
          5 #include <errno.h>
          6
          7 #define SIZE 124
          8 #define PRIOR 10
          9
         10 struct
         11 {
         12     long type;
         13     char data[SIZE];
         14 }msg_data;
         15
         16 int main()
         17 {
         18     int msqid;
         19     int data_len;
         20
         21     if((msqid = msgget((key_t)7878, IPC_CREAT |0666)) == -1)
         22     {
         23         perror("msgget failed");
         24         exit(1);
         25     }
         26
         27     while(1)
         28     {
         29         if((data_len = msgrcv(msqid, &msg_data, SIZE, (-1*PRIOR), IPC_NOWAIT)) == -1)
         30         {
         31             if(errno == ENOMSG)
         32             {
         33                 printf("no messgae\n");
         34                 break;
         35             }
         36
         37             perror("msgrcv failed");
         38             break;
         39         }
         40
         41         msg_data.data[data_len] = 0;
         42         printf("data : %s [%ld]\n", msg_data.data, msg_data.type);
         43     }
         44
         45     if(msgctl(msqid, IPC_RMID, 0== -1)
         46     {
         47         perror("msgctl failed");
         48         exit(1);
         49     }
         50
         51     return 0;
         52 }
         53





    실행화면


















    -----------------

    공유 메모리

    -----------------



    --- 공유 메모리

     공유 메모리란 여러 프로세스가 함께 이용할 수 있는 메모리를 말한다.

    모든 프로세스 전역변수? 같은 역할이다.



    공유메모리를 사용할 때에는


    1. 생성

    2. 첨부

    3. 분리

    4. 제거


    과정을 거친다.


    공유 메모리를 가져와서 바로 쓸 수 있는게 아니라

    공유 메모리를 자신의 메모리인 마냥 첨부 시켜야 한다고 한다.

    다 사용 후 분리를 시켜주고 제거하거나 한다.




    --- shmget

    공유 메모리 생성


    #include <sys/ipc.h>

    #include <sys/shm.h>


    int shmget(key_t key, int size, int shmflg);


    key : 시스템에서 식별하는 공유 메모리 번호

    size : 공유 메모리 크기

    shmflg : 동작 옵션

    IPC_CREAT : key에 해당하는 공유 메모리가 존재하지 않으면 생성하는데 접근 권한도 함께

    부여해야 한다. 만약 공유 메모리가 있으면 이 옵션은 무시.

    IPC_EXCL : 공유 메모리가 있으면 실패로 -1을 반환. 이 값이 설정되지 않으면 기존 공유

    메모리에 접근하여 식별자를 반환한다.



    리턴값

    성공시

    공유 메모리 식별자


    실패시

    -1






    --- shmat

    공유 메모리를 호출 프로세스 메모리로 첨부

    (공유 메모리는 자신의 메모리에 첨부해야만 자신의 메모리인 것처럼 사용 가능하다)


    #include <sys/types.h>

    #include <sys/shm.h>


    void * shmat(int shmid, const void * shmaddr, int shmflg);


    shmid : 공유 메모리 식별자

    shmaddr : 공유 메모리 주소, 일반적으로 NULL

    shmflg : 동작 옵션

    SHM_RDONLY : 읽기 전용으로 사용

    SHM_RND : shmaddr을 NULL



    리턴값

    성공시

    공유 메모리 주소 포인터


    실패시

    (void *)-1






    --- shmdt

    공유 메모리를 호출 프로세스 메모리에서 분리한다.


    #include <sys/types.h>

    #include <sys/shm.h>


    int shmdt(const void * shmaddr);


    shmaddr : 삭제할 공유 메모리 주소



    리턴값

    성공시

    0


    실패시

    -1





    --- shmctl

    공유 메모리 제어한다.


    #include <sys/ipc.h>

    #include <sys/shm.h>


    int shmctl(int shmid, int cmd, struct shmid_ds * buf);


    shmid : 공유 메모리 식별자

    cmd : 제어 종류

    IPC_STAT : 공유 메모리의 정보를 얻어 buf에 저장.

    IPC_SET : 공유 메모리의 정보를 buf에 저장한 값으로 변경한다. 단, shm_perm과 shm_ctime멤버에

    대한 정보만 변경할 수 있다.

    IPC_RMID : 공유 메모리를 제거. 이 때 세 번째 인수 buf는 0으로 지정.

    buf : 공유 메모리 정보에 대한 포인터

    struct shmid_ds

    {

    struct ipc_perm    shm_perm;        // 접근 권한

    int    shm_segsz;                        // 세그먼트 크기(바이트)

    time_t    shm_atime;                     // 최종 접근 시간

    time_t    shm_dtime;                     // 최종 제거 시간

    time_t    shm_ctime;                     // 최종 변경 시간

    unsigned short    shm_cpid;         // 생성 프로세스의 PID

    unisgned short    shm_lpid;          // 최종적으로 동작한 프로세스의 PID

    short    shm_nattch;                     // 현재 접근한 프로세스의 수

    unsigned short    shm_npages;     // 세그먼트의 크기(페이지)

    unsigned long *    shm_pages;     // 페이지 테이블 항목을 위한 필드

    struct shm_desc *    attaches;      // 접근을 위한 기술자들

    };



    리턴값

    성공시

    0


    실패시

    -1






    예제 소스)


    26_5.c


          1 #include <stdio.h>
          2 #include <string.h>
          3 #include <sys/types.h>
          4 #include <sys/ipc.h>
          5 #include <sys/shm.h>
          6 #include <signal.h>
          7
          8 #define SIZE 1024
          9
         10 void signalHandler(int signo);
         11 int shmid;
         12
         13 int main()
         14 {
         15     void *shmaddr;
         16
         17     if((shmid = shmget((key_t)7878, SIZE, IPC_CREAT | 0666)) == -1)
         18     {
         19         perror("shmid failed");
         20         exit(1);
         21     }
         22
         23     if((shmaddr = shmat(shmid, (void*)00)) == (void *) -1)
         24     {
         25         perror("shmat failed");
         26         exit(1);
         27     }
         28
         29     strcpy((char*)shmaddr, "Linux Programming");
         30
         31     if(shmdt(shmaddr) == -1)
         32     {
         33         perror("shmdt failed");
         34         exit(1);
         35     }
         36
         37     signal(SIGINT, signalHandler);
         38     pause();
         39
         40     return 0;
         41 }
         42
         43 void signalHandler(int signo)
         44 {
         45     if(shmctl(shmid, IPC_RMID, 0== -1)
         46     {
         47         perror("shmctl failed");
         48         exit(1);
         49     }
         50
         51     exit(0);
         52 }





    26_6.c


          1 #include <stdio.h>
          2 #include <sys/types.h>
          3 #include <sys/ipc.h>
          4 #include <sys/shm.h>
          5 #include <signal.h>
          6
          7 #define SIZE 1024
          8
          9 int main()
         10 {
         11     int shmid;
         12     void *shmaddr;
         13     struct shmid_ds shm_stat;
         14
         15     if((shmid = shmget((key_t)7878, SIZE, IPC_CREAT | 0666)) == -1)
         16     {
         17         perror("shmid failed");
         18         exit(1);
         19     }
         20
         21     if((shmaddr = shmat(shmid, (void*)00)) == (void *) -1)
         22     {
         23         perror("shmat failed");
         24         exit(1);
         25     }
         26
         27     printf("data read from shared memory : %s\n", (char *)shmaddr);
         28
         29     if(shmctl(shmid, IPC_STAT, &shm_stat) == -1)
         30     {
         31         perror("shmctl failed");
         32         exit(1);
         33     }
         34
         35     if(shmdt(shmaddr) == -1)
         36     {
         37         perror("shmdt failed");
         38         exit(1);
         39     }
         40
         41     kill(shm_stat.shm_cpid, SIGINT);
         42
         43     return 0;
         44 }




    실행화면












    ------------

    세마포어

    ------------



    --- 세마포어?

    세마포어란 여러 프로세스들이 한정된 자원을 사용할 때,

    한정된 수의 프로세스만 사용할 수 있게 해주는 방법이다.









    --- semget

    세마포어 집합을 생성.


    #include <sys/types.h>

    #include <sys/ipc.h>

    #include <sys/sem.h>


    int semget(key_t key, int nsems, int semflg);


    key : 세마포어 ID

    nsems : 생성할 세마포어 방 갯수

    semflg : 옵션

    IPC_CREAT : key에 해당하는 세마포어 ID가 없으면 접근 권한과 함께 생성.

    없으면 무시.

    IPC_EXCL : 세마포어 ID가 있으면 실패로 -1, 이 값을 설정해 주지 않으면

    기존 세마포어 ID에 접근하여 ID를 반환한다.



    리턴값

    성공시

    세마포어 ID


    실패시

    -1





    --- semctl

    세마포어 제어


    #include <sys/types.h>

    #include <sys/ipc.h>

    #include <sys/sem.h>


    int semctl(int semid, int semnum, int cmd, union semun arg);


    semid : 세마포어 ID

    semnum : 세마포어 내에 제어할 세마포어 방 번호

    0 이면 첫 번째 세마포어

    1 이면 두 번째 세마포어

    2 이면 세 번째 세마포어를 지칭한다.

    cmd : 제어

    GETVAL 세마포어의 현재 값을 구한다.

    GETPID 세마포어에 가장 최근에 접근했던 프로세스의 프로세스 ID를 구한다.

    GETNCNT 세마포어 값이 증가하기를 기다리는 프로세스의 개수

    GETZCNT 세마포어 값이 0 이 되기를 기다리는 프로세스의 개수

    GETALL 세마포어 집합의 모든 세마포어 값을 구한다.

    SETVAL 세마포어 값을 설정

    SETALL 세마퍼어 집합의 모든 세마포어 값을 설정

    IPC_STAT 세마포어의 정보를 구한다.

    IPC_SET 세마포어의 소유권과 접근 허가를 설정

    IPC_RMID 세마포어 집합을 삭제

    arg : cmd에 따라 다른 옵션



    리턴값

    성공시

    0 이상 양수


    실패시

    -1





    --- semop

    세마포어 연산


    #include <sys/types.h>

    #include <sys/ipc.h>

    #include <sys/sem.h>


    int semop(int semid, struct sembuf * sops, unsigned nsops);

    semid : 세마포어 ID
    sops : 연산할 내용
    struct sembuf
    {
    short sem_num;
    short sem_op;
    short sem_flg;
    };
    sem_flg
    IPC_NOWAIT : 호출 즉시 실행하지 못할 경우 기다리지 않고 실패로 -1 리턴
    IPC_UNDO : 프로세스가 종료되면 세마포어 설정을 원래 상태로 되돌린다.
    예기치 못한 종료에 세마포어를 원상복귀 시키지 못할 경우라도 복귀해 주기
    때문에 설정해 주는 것이 좋다.
    nsops : 연산할 갯수
    한 번 계산하면 1
    두 번 계산하면 2
    보통 1이겠지?


    리턴값
    성공시
    0

    실패시
    -1







    예제 소스)


          1 #include <stdio.h>
          2 #include <stdlib.h>
          3 #include <sys/types.h>
          4 #include <sys/ipc.h>
          5 #include <sys/sem.h>
          6
          7 void repeat(int semid);
          8 void p(int semid);
          9 void v(int semid);
         10
         11 main()
         12 {
         13     int semid, i;
         14     union semun {
         15        int val;
         16        struct semid_ds *buf;
         17        unsigned short int *array;
         18     } arg;
         19
         20     // 세마포어가 1개인 8877 키의 세마포어 집합 생성
         21     if((semid=semget((key_t)88771, IPC_CREAT|0666)) == -1) {
         22        perror("semget failed");
         23        exit(1);
         24     }
         25
         26     // 세마포어 값을 1로 설정
         27     arg.val = 1;
         28     if(semctl(semid, 0, SETVAL, arg) == -1) {
         29        perror("semctl failed");
         30        exit(1);
         31     }
         32
         33     // 3개의 자식 프로세스 생성
         34     for(i=0; i<3; i++) {
         35        if(!fork())
         36           repeat(semid);
         37     }
         38
         39     // 10초간 정지
         40     sleep(10);
         41
         42     // semid 세마포어 삭제
         43     if(semctl(semid, 0, IPC_RMID, arg) == -1) {
         44        perror("semctl failed");
         45        exit(1);
         46     }
         47     exit(0);
         48 }
         49
         50 void repeat(int semid)
         51 {
         52     // 난수 초기화하기
         53     srand((unsigned int)getpid());
         54     p(semid);
         55
         56     // getpid()는 현재 프로세스의 프로세스 ID를 반환
         57     printf("%d process is using tool\n", getpid());
         58
         59     // 난수를 5로 나눈 나머지 초 동안 정지
         60     sleep(rand()%5);
         61     printf("%d process is returning tool\n", getpid());
         62     v(semid);
         63
         64     exit(0);
         65 }
         66
         67 void p(int semid)
         68 {
         69     struct sembuf pbuf;
         70
         71     pbuf.sem_num = 0;
         72     pbuf.sem_op = -1;
         73
         74     // 프로세스 종료하면 세마포어 설정 원상 복귀
         75     pbuf.sem_flg = SEM_UNDO;
         76
         77     // 현재 세마포어 값인 semval 1 감소하기
         78     if(semop(semid, &pbuf, 1== -1) {
         79        perror("semop failed");
         80        exit(1);
         81     }
         82 }
         83
         84 void v(int semid)
         85 {
         86     struct sembuf vbuf;
         87     vbuf.sem_num = 0;
         88     vbuf.sem_op = 1;
         89     vbuf.sem_flg = SEM_UNDO;
         90     // 현재 세마포어 값인 semval 1 증가하기
         91     if(semop(semid, &vbuf, 1== -1) {
         92        perror("semop failed");
         93        exit(1);
         94     }
         95 }












    ------------

    select 함수

    ------------



    --- select

    파일 디스크립터들의 읽기, 쓰기, 오류를 감시한다.


           #include <sys/time.h>

           #include <sys/types.h>

           #include <unistd.h>


           int  select(int  n,  fd_set  *readfds,  fd_set  *writefds,

           fd_set *exceptfds, struct timeval *timeout);


           FD_CLR(int fd, fd_set *set);

           FD_ISSET(int fd, fd_set *set);

           FD_SET(int fd, fd_set *set);

           FD_ZERO(fd_set *set);




    fd_set



    http://www.joinc.co.kr/modules/moniwiki/wiki.php/Site/system_programing/File/select

Designed by Tistory.