부산IT학원/스마트컨트롤러

20140625 (메시지 큐 우선순위, 공유 메모리)

EHOzlO 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