1 메시지 큐란
2 System V 메시지 큐
2.1 메시지큐의 생성, 사용, 제어
#include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h> int msgget (key_t key, int msgflg) int msgsnd (int msqid, struct msgbuf *msgp, size_t msgsz, int msgflg) ssize_t msgrcv (int msqid, struct msgbuf *msgp, size_t msgsz, long msgtyp, int msgflg)
struct msqid_ds { struct ipc_perm msg_perm; /* structure describing operation permission */ __time_t msg_stime; /* time of last msgsnd command */ unsigned long int __unused1; __time_t msg_rtime; /* time of last msgrcv command */ unsigned long int __unused2; __time_t msg_ctime; /* time of last change */ unsigned long int __unused3; unsigned long int __msg_cbytes; /* current number of bytes on queue */ msgqnum_t msg_qnum; /* number of messages currently on queue */ msglen_t msg_qbytes; /* max number of bytes allowed on queue */ __pid_t msg_lspid; /* pid of last msgsnd() */ __pid_t msg_lrpid; /* pid of last msgrcv() */ unsigned long int __unused4; unsigned long int __unused5; };최초 msgget 를 이용해서 커널에 메시지큐를 요청하면, 커널은 해당 메시지큐를 위해 메모리를 할당하고, 메모리 관리와 그밖의 정보 관리를 위해 위의 구조체를 세팅하게 된다.
2.2 메시지큐 생성
2.3 메시지큐에 데이타 쓰기
struct msgbuf { long mtype; char mtext[255]; }위의 모습은 메시지 구조체의 매우 전형적인 모습으로 사실멤버변수는 필요에 따라서 얼마든지 변경될수 있다. 다만 long mtype 만이 필수요소이다.
2.4 메시지큐의 데이타 가져오기
2.5 예제를 통해 알아본 메시지큐
#include <sys/types.h #include <sys/ipc.h> #include <sys/msg.h> #include <sys/stat.h> struct msgbuf { long msgtype; char mtext[256]; char myname[16]; int seq; }; int main() { key_t key_id; int i; struct msgbuf mybuf, rcvbuf; key_id = msgget((key_t)1234, IPC_CREAT|0666); if (key_id == -1) { perror("msgget error : "); exit(0); } printf("Key is %d\n", key_id); memset(mybuf.mtext, 0x00, 256); memset(mybuf.myname, 0x00, 16); memcpy(mybuf.mtext, "hello world 4", 13); memcpy(mybuf.myname, "yundream", 8); mybuf.seq = 0; i = 0; while(1) { // 짝수일경우 메시지 타입이 4 // 홀수일경우에는 메시지 타입이 3 if (i % 2 == 0) mybuf.msgtype = 4; else mybuf.msgtype = 3; mybuf.seq = i; // 메시지를 전송한다. if (msgsnd( key_id, (void *)&mybuf, sizeof(struct msgbuf), IPC_NOWAIT) == -1) { perror("msgsnd error : "); exit(0); } printf("send %d\n", i); i++; sleep(1); } printf("%d \n", rcvbuf.msgtype); printf("%s \n", rcvbuf.mtext); printf("%s \n", rcvbuf.myname); exit(0); }프로그램은 간단하다. mybuf 란 구조체를 만들어서 메시지를 전송하는데, 이때 메시지 타입을 i % 2 가 0일경우 4로 그렇지 않을경우 3으로 해서 전송을 하도록 만들었다.
#include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h> #include <sys/stat.h> struct msgbuf //구조체도 헤더파일에서 선언된 것과 겹치는 현상이 일어나서 컴파일이 되질 않습니다. 구조체 이름도 바꾸어야합니다. { long msgtype; char mtext[256]; char myname[16]; int seq; }; int main(int argc, char **argv) { key_t key_id; struct msgbuf mybuf; int msgtype;//전역변수로 빼야 됩니다. // 아규먼트가 있을경우 msgtype 가 3인 메시지를 받아오고(홀수) // 아규먼트가 없을경우 msgtype 가 4인 메시지를 받아온다(짝수) if (argc == 2) msgtype = 3; else msgtype = 4; key_id = msgget(1234, IPC_CREAT|0666); if (key_id < 0) { perror("msgget error : "); exit(0); } while(1) { if (msgrcv( key_id, (void *)&mybuf, sizeof(struct msgbuf), msgtype, 0) == -1) { perror("msgrcv error : "); exit(0); } printf("%d\n", mybuf.seq); } exit(0); }
2.6 메시지큐의 제어
IPC_SET msqid_ds 구조체 정보를 변경하고자 할때 사용한다. 주로 퍼미션 정보를 바꾸기 위해서 사용한다. IPCRMID 현재 메시지큐를 제거한다.
2.7 정리
3 POSIX 메시지 큐
3.1 메세지 큐 만들기
$ mkdir /dev/mqueue $ mount -t mqueue none /dev/mqueue생성된 디렉토리는 자동으로 sticky bit가 설정된다.
#include <fcntl.h> #include <sys/stat.h> #include <mqueue.h> 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);mq_open 함수는 name이름을 가지는 메시지 큐를 만든다. 매개변수 oflag는 큐의 생성방식을 정의 하기 위해서 사용한다.mode는 권한을 설정하기 위해서 사용한다. 자세한 내용은 man page 문서를 참고하자.
struct mq_attr { long mq_flags; /* 0 or O_NONBLOCK */ long mq_maxmsg; /* 메시지 큐의 크기. 들어갈 수 있는 아이템의 수 */ long mq_msgsize; /* 메시지 크기로 바이트 단위 */ long mq_curmsgs; /* }
$ cat /dev/mqueue/q.123 QSIZE:0 NOTIFY:0 SIGNO:0 NOTIFY_PID:0각 필드에 대해서 살펴보자.
- QSIZE : 큐에 있는 모든 메시지의 바이트 크기
- NOTIFY_PID :
- NOTIFY :
- SIGNO :
3.2 예제
3.2.1 mq_server
#include <stdlib.h> #include <fcntl.h> #include <mqueue.h> #include <stdio.h> int main(int argc, char **argv) { struct mq_attr attr; attr.mq_maxmsg = 10; attr.mq_msgsize = 4; int value; mqd_t mfd; mfd = mq_open("/my_mq", O_RDWR | O_CREAT, 0666, &attr); if (mfd == -1) { perror("open error"); exit(0); } while(1) { if((mq_receive(mfd, (char *)&value, attr.mq_msgsize,NULL)) == -1) { exit(-1); } printf("Read Data %d\n", value); } }
3.2.2 mq_client
#include <stdlib.h> #include <fcntl.h> #include <mqueue.h> #include <stdio.h> int main(int argc, char **argv) { struct mq_attr attr; attr.mq_maxmsg = 10; attr.mq_msgsize = 4; int value = 0; mqd_t mfd; mfd = mq_open("/my_mq", O_WRONLY, 0666, &attr); if(mfd == -1) { perror("open error"); exit(0); } while(1) { if((mq_send(mfd, (char *)&value, attr.mq_msgsize, 1)) == -1) { perror("send error"); exit(-1); } sleep(1); value ++; } }
[출처] http://www.joinc.co.kr/modules/moniwiki/wiki.php/Site/system_programing/IPC/MessageQueue