메시지큐, 공유메모리 등 더 많은 정보와 예제코드를 담은 리눅스 교재를 배포했습니다. 아래의 페이지에서 리눅스 교재를 받아가세요.

https://reakwon.tistory.com/233

 

리눅스 프로그래밍 note 배포

티스토리에 리눅스에 관한 내용을 두서없이 여지껏 포스팅했었데요. 저도 제 포스팅을 찾기가 어렵기도 하고 티스토리에서 코드삽입을 하게 되면 이게 일자로 쭉 쓰여져있는 x같은 현상이 생겨

reakwon.tistory.com

 

Message Queue

프로세스 간 통신 방식인 IPC기법 중 하나인 메시지 큐는 두 가지 사용 방법이 있습니다. msgget, msgsend, msgrecv와 같은 함수를 사용하는 방식인 System V 방식의 메시지큐, 그리고 지금 알아볼 mq_open, mq_send, mq_recv와 같은 함수를 사용하는 방식인 POSIX 방식이 있습니다. 

System V의 메시지 큐를 사용하는 방법과 예제를 보시려면 아래의 포스팅을 방문하여 확인해보세요.

https://reakwon.tistory.com/97

 

[리눅스] 메시지 큐(message queue) 개념과 예제(msgget, msgsnd, msgrcv, msgctl)

메시지 큐 IPC기법 중 하나인 메시지큐는 Data Structure 중 큐를 사용합니다. 기본적으로는 먼저온 메시지가 먼저 꺼내어집니다. 메시지큐의 msgtype에 따라 특정 메시지 중 가장 먼저들어온 메시지도

reakwon.tistory.com

 

System V는 옛날 유닉스 방식으로 보시면 되구요. 이후에 나온것이 POSIX입니다. POSIX는 Portable Operating System Interface라고 해서 이식 가능 운영체제 인터페이스라고 합니다. 리눅스가 POSIX를 준수하는 운영체제이구요. 

우선 다음의 헤더파일들이 필요합니다. 

#include <fcntl.h>           /* For O_* constants */
#include <sys/stat.h>        /* For mode constants */
#include <mqueue.h>

 

컴파일할때는 -lrt로 링크를 걸어줘야하구요. 아래에서 코드를 실행하고 컴파일할때 다 설명할겁니다.

1) mq_open

mqd_t mq_open(const char *name, int oflag);
mqd_t mq_open(const char *name, int oflag, mode_t mode, struct mq_attr *attr);

 

메시지 큐를 여는 함수로 2개가 존재하네요. mode와 메시지 큐의 속성을 정의하는 attr도 같이 넘겨줄수 있는 함수가 따로 존재합니다. 

name : 메시지 큐 이름을 지정합니다.

oflag : 메시지큐에 옵션을 줄 수 있습니다. 아래와 같은 flag들이 존재합니다. 아래의 flag를 쓰려고 fcntl.h 파일을 include해야하는 겁니다.

flag 설명
O_RDONLY 읽기(메시지 받기:recv) 전용으로 메시지 큐를 엽니다. 
O_WRONLY 쓰기(메시지 전송:send) 전용으로 메시지 큐를 엽니다.
O_RDWR 읽기, 쓰기 전용으로 메시지 큐를 엽니다.
O_CLOEXEC close-on-exec이라고 하여, exec시 메시지큐를 닫습니다.
O_CREAT 메시지 큐가 존재하지 않으면 메시지큐를 생성합니다. 이 플래그를 사용하려면 두가지 인자가 추가로 더 필요한데 그게 바로 mode와 attr입니다.
O_EXCL O_CREAT과 같이 사용하여 이미 파일이 존재하면 EEXIST에러를 발생시킵니다.
O_NONBLOCK 비블록 형식으로 메시지큐를 엽니다. mq_send나 mq_receive시에 메시지가 없으면 지속적으로 기다리게 되는데, 이 플래그를 사용하면 기다리지 않습니다.

 

mode : O_CREAT과 같이 사용합니다. 메시지큐를 만들때 권한을 설정합니다.

attr : mq_attr의 포인터로 다음과 같이 정의되어있습니다. 메시지큐의 속성을 지정하는데, 최대 메시지수, 최대 메시지 사이즈(바이트) 등을 정할 수 있습니다.

 struct mq_attr {
       long mq_flags;       /* Flags (ignored for mq_open()) */
       long mq_maxmsg;      /* Max. # of messages on queue */
       long mq_msgsize;     /* Max. message size (bytes) */
       long mq_curmsgs;     /* # of messages currently in queue
                                       (ignored for mq_open()) */
};

반환 : 만약 메시지큐가 올바르게 생성되었다면 메시지큐를 제어할 수 있는 mqd_t가 반환됩니다. 우리는 이것을 통해서 메시지를 주고 받을 수 있습니다.

 

2) mq_send, mq_timedsend

int mq_send(mqd_t mqdes, const char *msg_ptr,nsize_t msg_len, unsigned int msg_prio);

#include <time.h>
int mq_timedsend(mqd_t mqdes, const char *msg_ptr, size_t msg_len, unsigned int msg_prio,
                     const struct timespec *abs_timeout);

 

메시지를 보내는 함수는 두가지가 존재합니다. 

mqdes : mq_open시에 받은 mqd_t입니다. 

msg_ptr : char형 메시지 포인터입니다. 메시지 내용을 의미합니다.

msg_len : 이름에서 알 수 있듯이 메시지의 크기를 의미합니다.

msg_prio : 메시지의 우선순위를 지정합니다.

abs_timeout : 지정된 시간동안 메시지 전송을 보류합니다. 큐가 꽉 찼을 경우가 있을 경우에 말이죠. NON_BLOCK 플래그가 없어야합니다. timespec 구조체는 아래와 같습니다. 이 구조체를 사용하기 위해서 time.h가 필요합니다.

struct timespec {
       time_t tv_sec;        /* seconds */
       long   tv_nsec;       /* nanoseconds */
};

 

반환 : 성공시 0, 실패시 -1을 반환합니다.

 

3) mq_receive, mq_timedreceive

ssize_t mq_receive(mqd_t mqdes, char *msg_ptr, size_t msg_len, unsigned int *msg_prio);

#include <time.h>
ssize_t mq_timedreceive(mqd_t mqdes, char *msg_ptr, size_t msg_len, unsigned int *msg_prio,
                          const struct timespec *abs_timeout);

 

자, 메시지를 보냈으니까 받아야겠죠. mq_send와 받는다는 것 외에는 모두 똑같습니다. msg_ptr에 메시지가 들어오게 됩니다. 그리고 mq_timedreceive를 통해서 역시 메시지가 쌓일때까지 지정된 시간만큼 기다릴수 있습니다.

반환 : 만약 올바르게 받았다면 실제로 받은 메시지의 사이즈가 반환되고 실패할 경우 -1이 반환됩니다. 

혹시 Message too long 에러가 발생한다면, 이것은 mq_receive 계열 함수에서 발생할 수 있는 에러인데, mq_receive의 man 페이지에서는 아래와 같이 설명하고 있습니다. mq_receive의 msg_len의 값은 attribute에서 설정한 mq_msgsize보다 작으면 안됩니다. (msg_len >= mq_msgsize)

 EMSGSIZE
              msg_len was less than the mq_msgsize attribute of the message queue.

 

4) mq_close

int mq_close(mqd_t mqdes);

 

mqdes : 닫을 mq를 지정합니다.

반환 : 성공시 0, 실패시 -1을 반환합니다. 

 

mq 기본예제

다음의 server.c는 메시지큐를 열고 받은 메시지를 출력하는 아주 간단한 역할을 합니다.

server.c

#include <stdlib.h>
#include <fcntl.h>
#include <stdio.h>
#include <mqueue.h>
#include <sys/stat.h>

int main()
{
    struct mq_attr attr;
    //attr 때문에 에러 발생할 수 있음
    attr.mq_maxmsg = 20;
    attr.mq_msgsize = 128;
    char buf[128] = {0,};

    mqd_t mq;

    mq = mq_open("/reakwon_mq", O_RDWR | O_CREAT,  0666, &attr);
    if (mq == -1)
    {
            perror("message queue open error");
            exit(1);
    }

    if((mq_receive(mq, buf, attr.mq_msgsize,NULL)) == -1){
            perror("mq_receive error");
            exit(-1);
    }
    printf("mq received : %s\n", buf);
    mq_close(mq);
}

 

그리고 client.c는 메시지큐를 열고 메시지를 보내는 아주 간단한 프로그램이죠.

 

client.c

#include <stdlib.h>
#include <fcntl.h>
#include <mqueue.h>
#include <stdio.h>
#include <string.h>
int main(int argc, char **argv)
{
    struct mq_attr attr;
    //attr때문에 에러가 발생할 수 있음
    attr.mq_maxmsg = 20;
    attr.mq_msgsize = 128;
    mqd_t mq;
    char buf[128] = {0,};

    mq = mq_open("/reakwon_mq", O_WRONLY, 0666, &attr);
    if(mq == -1){
        perror("open error");
        exit(0);
    }

    scanf("%s", buf);
    if((mq_send(mq, buf, strlen(buf), 1)) == -1){
            perror("mq_send error");
            exit(-1);
    }
    mq_close(mq);
}

 

server.c와 client.c의 메시지큐 이름은 같아야합니다. 그리고 아래와 같이 컴파일해보도록 하죠. 아까 -lrt로 링크걸어줘야한다고 했죠?

# gcc server.c -o server -lrt
# gcc client.c -o client -lrt

 

그리고 server를 백그라운드로 실행시키고, client를 실행하여 메시지를 보내려고 하는 순간, 리눅스 세계는 그렇게 호락호락하지가 않죠. 아마도 아래의 에러 메시지가 발생할 수가 있습니다.

Invalid argument!

 

리눅스 시스템마다 message queue의 메시지 최대 사이즈라던가 큐의 크기가 정해져있는 한계(limit)이 있습니다. 어떻게 볼 수 있을까요? 아래의 경로에서 파일을 cat으로 확인할 수 있습니다.

/proc/sys/fs/mqueue/

 

여기서 메시지큐의 최대 크기와 메시지의 최대 크기를 볼까요? 

# cat /proc/sys/fs/mqueue/msgsize_max
8192
# cat /proc/sys/fs/mqueue/msg_max
10

 

위처럼 각 메시지의 최대 사이즈는 8192, 큐의 최대 들어갈 수 있는 메시지는 10개 입니다. 그래서 invalid argument 에러가 발생한 건데, 방법은 두 가지 입니다. 1. attr을 아래와 같이 시스템 limit에 맞게 수정하던지, 아니면 2. /proc/sys/fs/mqueue 안의 파일 내용을 강제로 고치던지 말이죠. 

1. attr 수정

attr.mq_maxmsg = 10;
attr.mq_msgsize = 8192;
char buf[8192] = {0,};

 

2. 루트 권한으로 아래 명령어 수행

echo 20 > /proc/sys/fs/mqueue/msg_max

 

이후에 컴파일 후 다시 수행해보시기 바랍니다.

# ./server &
[3] 17126
# ./client
hello?
mq received : hello?

 

서버는 받은 메세지를 정상적으로 출력하고 있네요. 

그런데, 메시지 큐는 어디에 실제로 생성이 될까요? 메시지큐가 실제 생성된 경로는 /dev/mqueue/ 하위에 mq_open시에 지정했던 mq 이름으로 존재하고 있습니다. 알아두는게 좋겠죠?

 

server.c의 코드를 아래와 같이 변경해봅시다. 아래의 코드는 mq_timedreceive를 통해서 일정 10초간 큐에 데이터가 없으면 곧장 종료하게 됩니다. 


#include <stdlib.h>
#include <fcntl.h>
#include <stdio.h>
#include <mqueue.h>
#include <sys/stat.h>
#include <time.h>

int main()
{
    struct mq_attr attr;
    attr.mq_maxmsg = 20;
    attr.mq_msgsize = 128;
    char buf[128] = {0,};

    mqd_t mq;
    struct timespec tm;

    mq = mq_open("/reakwon_mq", O_RDWR | O_CREAT,  0666, &attr);
    if (mq == -1)
    {
            perror("message queue open error");
            exit(1);
    }

    clock_gettime(CLOCK_REALTIME, &tm);
    tm.tv_sec += 10;    //현재 시간 + 10초
    if(mq_timedreceive(mq, buf, attr.mq_msgsize, 0, &tm) == -1){
            perror("mq_receive error");
            exit(-1);
    }
    printf("mq received : %s\n", buf);
    mq_close(mq);
}

 

컴파일하고 서버를 실행시켜 10초간 대기해보세요. 아래와 같이 종료하게 됩니다.

# ./server
mq_receive error: Connection timed out

 

단, 그전에 클라이언트를 실행해서 큐에 데이터가 쌓여있다면 그 큐에 있던 데이터가 출력이 됩니다. 

여기까지 POSIX의 메시지 큐 활용에 대해서 알아보았습니다.

반응형
블로그 이미지

REAKWON

와나진짜

,

메시지큐, 공유메모리 등 더 많은 정보와 예제를 담은 리눅스 교재를 배포했습니다. 아래의 페이지에서 리눅스 교재를 받아가세요.

https://reakwon.tistory.com/233

 

리눅스 프로그래밍 note 배포

티스토리에 리눅스에 관한 내용을 두서없이 여지껏 포스팅했었데요. 저도 제 포스팅을 찾기가 어렵기도 하고 티스토리에서 코드삽입을 하게 되면 이게 일자로 쭉 쓰여져있는 x같은 현상이 생겨

reakwon.tistory.com

 

메시지 큐

IPC기법 중 하나인 메시지큐는 Data Structure 중 큐를 사용합니다. 기본적으로는 먼저온 메시지가 먼저 꺼내어집니다. 메시지큐의 msgtype에 따라 특정 메시지 중 가장 먼저들어온 메시지도 받아올 수 있습니다. 이 메시지는 커널에서 보관하고 있으니 프로세스가 종료되어도 사라지지 않습니다.

메시지 큐의 용량이 허용하는 한 메시지는 계속 큐에 쌓일 수 있습니다. 메시지를 얻어오는 쪽은 가장 메시지를 읽고 메시지큐에서 그 메시지를 삭제합니다.

 

메시지 큐에는 두가지의 종류가 있습니다.

- System V의 Message Queue

- POSIX의 Message Queue

mq_open, mq_send, mq_receive와 같은 함수를 사용하는 POSIX에서 메시지큐 활용방법을 알아보시려면 아래의 포스팅을 참고하시면 됩니다.

https://reakwon.tistory.com/209

 

[리눅스] POSIX 메시지 큐 사용 방법 - 예제 코드

Message Queue 프로세스 간 통신 방식인 IPC기법 중 하나인 메시지 큐는 두 가지 사용 방법이 있습니다. msgget, msgsend, msgrecv와 같은 함수를 사용하는 방식인 System V 방식의 메시지큐, 그리고 지금 알아

reakwon.tistory.com

이번 포스팅에서는 System V의 Message Queue를 리눅스에서 어떻게 이용할 수 있는지 알아보도록 합시다.

 

메시지 큐 관련 시스템 콜

메시지큐를 사용하기 위해서는 3개의 헤더파일이 필요합니다.

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

 

1) msgget : System V의 메시지 큐 id를 얻어옵니다.

 int msgget(key_t key, int msgflg);

 

key : 메시지큐를 얻어올 때 사용하는 고유 key값입니다.

msgflg : flag에는 2가지가 있는데요. IPC_CREAT과 IPC_EXCL입니다.

 - IPC_CREAT : 메시지큐가 없으면 새로 생성합니다.

 - IPC_EXCL : IPC_CREAT과 같이 사용하는 flag인데, 만약 해당 메시지큐가 존재하면 msgget은 오류를 반환합니다.

 

2) msgsnd : 메시지를 보냅니다. 

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을 반드시 명시해주어야합니다. 

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

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

msgflg : 큐의 공간이 없을때 msgsnd의 동작은 blocking입니다. 즉, msgsnd에서 큐의 공간이 생겨날때까지 기다리는 것이지요. 여기서 IPC_NOWAIT을 사용한다면 msgsnd는 blocking되지 않고 실패합니다.

msgsnd가 성공적으로 동작하면 msqid_ds라는 구조체의 필드의 값이 변경됩니다. sys/msg.h에 이 구조체가 정의되어있습니다.

 

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) */
};

이 구조체는 메시지큐의 메타데이터같은 것인데 msgsnd를 성공적으로 호출하고 나면 아래와 같이 변경됩니다.

- msg_lspid는 호출된 process id로 변경

- msg_qnum의 값 1 증가

- msg_stime을 현재 시간으로 설정

 

3) msgrcv : msgsnd를 했다면 받는 시스템 콜이 있어야겠지요. msgrcv가 그 역할을 합니다. 메시지큐 id의 메시지를 하나 읽고 그 메시지를 큐에서 제거합니다.

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

 

msqid : 다 아시겠지만 메시지큐 id입니다.

msgp : 읽어들인 메시지를 msgp가 가리키는 주소에 위치시킵니다. 쉽게말해 읽어온 메시지입니다.

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

msgtyp : 0, >0, <0으로 동작이 나뉩니다.

msgtyp == 0 큐의 첫번째 메시지를 읽어옵니다.
msgtyp > 0 그 값과 동일한 메시지 타입을 갖는 메시지를 반환합니다. 
msgtyp < 0 msgtyp의 절대값 이하의 가장 작은 메시지를 읽어옵니다.

msgflg : 4개 정도의 flag가 있습니다. 

- IPC_NOWAIT

- MSG_COPY : 리눅스 3.8이상부터 지원합니다.

- MSG_EXCEPT

- MSG_NOERROR

 

4) msgctl : 메시지큐를 제어하기 위한 시스템 콜입니다. 

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

msqid : 다들 아시죠? 메시지 큐 id입니다.

cmd : 제어할 command입니다. 몇개 있는데 3개만 보도록 하겠습니다.

- IPC_STAT : buf로 메시지큐 정보를 읽어옵니다. 

- IPC_SET : buf로 메시지큐 정보를 설정합니다.

- IPC_RMID : 메시지큐를 지웁니다.

buf : 아까 위에서 보았던 구조체네요. cmd로 IPC_STAT과 IPC_SET을 사용할때 전달해주면 되고 

딱히 필요없으면 NULL을 전달합니다.

 

이제 메시지큐를 통한 예제를 볼까요?

아래의 예제는 sender에서 어떤 사람의 나이와 이름을 receiver에게 전달하는 메시지 큐 예제입니다. sender에서는 메시지큐의 정보 또한 보여주고 있습니다. 메시지 큐에 있는 message라는 구조체는 sender와 receiver가 사용하고 있으므로 헤더파일 msg_data.h를 두어 같이 사용합니다.

 

예제는 너무 간단하기 때문에 따로 설명할 필요는 없고 한번 따라 해보면 다 이해하실거에요.

 

msg_data.h

struct real_data{
        short age;
        char name[16];
};
struct message{
        long msg_type;
        struct real_data data;
};

 

sender.c

#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/types.h>
#include <sys/msg.h>
#include <stdlib.h>
#include <string.h>
#include "msg_data.h"


void printMsgInfo(int msqid){

        struct msqid_ds m_stat;
        printf("========== messege queue info =============\n");
        if(msgctl(msqid,IPC_STAT,&m_stat)==-1){
                printf("msgctl failed");
                exit(0);
        }
        printf(" message queue info \n");
        printf(" msg_lspid : %d\n",m_stat.msg_lspid);
        printf(" msg_qnum : %d\n",m_stat.msg_qnum);
        printf(" msg_stime : %d\n",m_stat.msg_stime);

        printf("========== messege queue info end =============\n");
}
int main(){
        key_t key=12345;
        int msqid;

        struct message msg;
        msg.msg_type=1;
        msg.data.age=80;
        strcpy(msg.data.name,"REAKWON");

        //msqid를 얻어옴.
        if((msqid=msgget(key,IPC_CREAT|0666))==-1){
                printf("msgget failed\n");
                exit(0);
        }

        //메시지 보내기 전 msqid_ds를 한번 보자.
        printMsgInfo(msqid);

        //메시지를 보낸다.
        if(msgsnd(msqid,&msg,sizeof(struct real_data),0)==-1){
                printf("msgsnd failed\n");
                exit(0);
        }

        printf("message sent\n");
        //메시지 보낸 후  msqid_ds를 한번 보자.
        printMsgInfo(msqid);
}

 

receiver.c 

#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/types.h>
#include <sys/msg.h>
#include <stdlib.h>
#include <string.h>
#include "msg_data.h"

int main(){
        key_t key=12345;
        int msqid;
        struct message msg;

        //받아오는 쪽의 msqid얻어오고
        if((msqid=msgget(key,IPC_CREAT|0666))==-1){
                printf("msgget failed\n");
                exit(0);
        }
        //메시지를 받는다.
        if(msgrcv(msqid,&msg,sizeof(struct real_data),0,0)==-1){
                printf("msgrcv failed\n");
                exit(0);
        }

        printf("name : %s, age :%d\n",msg.data.name,msg.data.age);

        //이후 메시지 큐를 지운다.
        if(msgctl(msqid,IPC_RMID,NULL)==-1){
                printf("msgctl failed\n");
                exit(0);
        }
}

 

두개의 c파일을 컴파일 해줍시다.

# gcc sender.c -o sender
# gcc receiver.c -o receiver

 

이제 sender부터 실행하도록 합시다.

# ./sender
========== messege queue info =============
 message queue info
 msg_lspid : 0
 msg_qnum : 0
 msg_stime : 0
========== messege queue info end =============
message sent
========== messege queue info =============
 message queue info
 msg_lspid : 5129
 msg_qnum : 1
 msg_stime : 1586521322
========== messege queue info end =============

 

메시지 큐의 정보가 변경된 것을 알 수있네요. 메시지가 성공적으로 보내졌나봅니다.

ipcs를 구경해볼까요?

# ipcs -q

------ Message Queues --------
key        msqid      owner      perms      used-bytes   messages
0x00003039 5          root       666        18

 

0x3039는 우리가 정한 key 12345입니다. sender 프로그램이 끝나고 메시지 큐는 아직 남아있습니다. 

이제 receiver를 실행해보도록 하지요.

# ./receiver
name : REAKWON, age :80

 

음, 잘 읽히네요. 한번더 receiver를 실행하면 아무런 동작을 하지 않습니다. 메시지큐에 아무것도 없기 때문입니다. ipcs를 들여다보면 메시지큐가 삭제되었네요. 그 이유는 receiver 코드를 보면 msgctl에서 cmd를 IPC_RMID를 주어 제거했기 때문입니다. 

# ipcs -q

------ Message Queues --------
key        msqid      owner      perms      used-bytes   messages

 

이상으로 메시지큐와 관련한 포스팅을 마치도록 하겠습니다. 긴글 읽어주셔서 감사합니다.

반응형
블로그 이미지

REAKWON

와나진짜

,