message queue

sesame·2022년 2월 8일
0

교육

목록 보기
28/46

매핑된 shared memory segment를 attach하는 함수

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

SHM_RND: shmaddr이 0이 아니고 사용자가 지정하였을 때 사용하는 flag
shmaddr이 SHMLBA의 배수이지 않으면 shmaddr보다 작은 주소 중에서 SHMLBA의 배수인 가장 가까운 memory 번지에 attach된다.
그렇지 않으면, page의 시작 위치 주소에 attach된다.
SHMLBA: shmat()에 대한 호출에서 첨부 주소를 명시적으로 지정할 때 호출자는 주소가 이 값의 배수인지 확인해야 한다. SHMLBA는 일반적으로 시스템 페이지 크기의 일부 배수
-- 주소는 페이지 정렬이 되어야하기 때문에


IPC_PRIVATE
유일한 ID를 가지는 IPC를 생성
IPC_PRIVATE는 일반적으로 IPC_CREATE와 함께 쓰임
IPC_CREATE만 쓸 때 key에 해당하는 메모리가 존재하지 않으면 새로 만들고, 존재하면 해당 공유 메모리 식별자를 가져옴
IPC_PRIVATE과 함께 쓰면 key에 해당하는 메모리가 이미 존재하면 -1을
return
-- 기존의 메모리에 접근하는 것을 방지하고 항상 새로운 메모리를 만들고자 할 때 사용

message queue

PC기법 중 하나인 메시지큐는 Data Structure 중 큐를 사용
기본적으로는 먼저온 메시지가 먼저 꺼내어진다.
메시지큐의 msgtype에 따라 특정 메시지 중 가장 먼저들어온 메시지도 받아올 수 있다.
이 메시지는 커널에서 보관하고 있으니 프로세스가 종료되어도 사라지지 않는다.
메시지 큐의 용량이 허용하는 한 메시지는 계속 큐에 쌓일 수 있다.
메시지를 얻어오는 쪽은 가장 메시지를 읽고 메시지큐에서 그 메시지를 삭제한다.

#include <sys/msg.h> 
#include <sys/ipc.h> 
#include <sys/types.h>

msgget(2)

메시지 큐 id 가져옴

int msgget(key_t key, int msgflg);

key: 메시지큐를 얻어올 때 사용하는 고유 key 값
msgflg:

  • IPC_CREAT: 메시지큐가 없으면 새로 생성
  • IPC_EXCL: IPC_CREAT과 같이 사용하는 flag인데, 만약 해당 메시지큐가 존재하면 msgget은 오류를 반환

msgsnd(2)

메시지를 보냄

int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);

msqid: 메시지 큐의 id
msgp: msgp는 void* 이나 우리는 구조체 형식으로 아래와 같이 정의해야함

struct msgbuf {
       long mtype;       /* message type, must be > 0 */
       char mtext[1];    /* message data */
};
  • mtype: 메시지의 타입, 이 값은 0보다 커야함
    메시지큐의 msgbuf를 정의할때 long형의 mtype을 반드시 명시
    이 mytype을 각각 다르게 줌으로써, 특정 프로세스에서 특정메시지를 참조할 수 있도록 만들수 있다. 예를 들어 A라는 프로세스가 A'라는 메시지 타입을 참조해야하고, B는 B'를 참조하도록 해야한다면, msgbuf를 만들 때 A'는 1 B'는 2 이런식으로 메시지ㅣ타입을 정의하고 A는 mytype가 1인것을 B는 mytype이 2인것을 가지고 가도록 하면된다.
    (mytype을 이용해서 자신이 원하는 메시지에만 선택적으로 접근이 가능)

  • mtext: mtext은 실제 메시지 큐에 보낼 데이터
    mtext와 같이 배열일 수도 있고, 구조체일 수도 있다.

msgsz: msgsz는 메시지 큐에 전송할 데이터의 사이즈
위의 msgbuf의 mtype멤버를 제외한 실데이터의 크기를 전달해야함

msgflg: 큐의 공간이 없을때 msgsnd의 동작은 blocking(큐의 공간이 생겨날때까지 기다리는 것)

  • IPC_NOWAIT: msgsnd는 blocking되지 않고 실패합니다.

return 성공시 msqid_ds 구조체 필드 값 변경

struct msqid_ds {
       struct ipc_perm msg_perm;     /* Ownership and permissions */
       time_t          msg_stime;    /* Time of last msgsnd(2) */
       time_t          msg_rtime;    /* Time of last msgrcv(2) */
       time_t          msg_ctime;    /* Time of last change */
       unsigned long   __msg_cbytes; /* Current number of bytes in queue (nonstandard) */
       msgqnum_t       msg_qnum;     /* Current number of messages in queue */
       msglen_t        msg_qbytes;   /* Maximum number of bytes allowed in queue */
       pid_t           msg_lspid;    /* PID of last msgsnd(2) */
       pid_t           msg_lrpid;    /* PID of last msgrcv(2) */
};

msqid_ds 구조체는 메타데이터같은 것인데 msgsnd를 성공적으로 호출하고 나면 아래와 같이 변경

  • msg_lspid는 호출된 process id로 변경
  • msg_qnum의 값 1 증가
  • msg_stime을 현재 시간으로 설정

msgrcv(2)

msgsnd를 했다면 받는 역할을 하는 시스템 콜
메시지 큐 id의 메시지를 하나 읽고 그 메시지를 큐에서 제거

ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);

msqid: 메시지큐 id
msgp: 읽어들인 메시지를 msgp가 가리키는 주소에 위치(쉽게말해 읽어온 메시지)

msgsz: 메시지를 읽을 크기(더 정확히는 msgbuf의 mtext 크기)
만약 읽어들인 메시지가 지정된 크기보다 크다면 msgflg에 따라 동작이 결정
만약 msgflg가 MSG_NOERROR라면 메시지를 읽어들이나 잘려서 읽히게 됩니다. MSG_NOERROR가 명시되어있지 않다면 메시지를 읽어오지 않고 msgrcv 시스템콜은 -1을 반환합니다.

msgtyp: 0, >0, <0으로 동작이 나뉨
msgtyp == 0 큐의 첫번째 메시지를 읽음
msgtyp > 0 그 값과 동일한 메시지 타입을 갖는 메시지를 반환
msgtyp < 0 msgtyp의 절대값 이하의 가장 작은 메시지를 읽음

msgflg:

  • IPC_NOWAIT: 메시지 큐에 메시지가 없으면 실패로 -1반환, 이 값을 설정하지 않으면 메시지가 큐에 도착할때까지 대기
  • MSG_EXCEPT: msgtyp이 0보다 크면 message type이 일치하지 않는 message를 수신
    msgtype이 0보다 큰 경우 msgtype과 다른 메시지 유형으로 대기열의 첫 번째 메시지를 읽을 때 사용됨
    gcc 할때 -D_GNU_SOURCE 커맨드 줘야함
    0:
    1:
    ..?
  • MSG_NOERROR: 메시지를 읽어들이나 잘려서 읽음, 이 값을 설정하지 않으면 -1 반환
    기본 출력:
    설정 o:
    설정 x:

msgctl(2)

메시지큐를 제어하기 위한 시스템 콜

int msgctl(int msqid, int cmd, struct msqid_ds *buf);

msqid : 메시지 큐 id
cmd : 제어할 command

  • IPC_STAT: buf로 메시지큐 정보를 읽어옴
  • IPC_SET: buf로 메시지큐 정보를 설정
  • IPC_RMID: 메시지큐를 지움

buf: cmd로 IPC_STAT과 IPC_SET을 사용할때 전달, 필요없으면 NULL

메시지 큐 확인하기
ipcs -q
옵션으로 q 말고 다른 옵션을 부여하면
해당 명령어를 통해 메시지 큐 외에도 현재 구동중인 IPC 관련 정보를 볼 수 있다.
메시지 큐 삭제하기
ipcrm -q msqid
해당 msqid를 사용하는 메시지큐를 삭제

0개의 댓글