SYSTEM CALL: msgsnd(); PROTOTYPE: int msgsnd ( int msqid, struct msgbuf *msgp, int msgsz, int msgflg ); RETURNS: 0 on success -1 on error: errno = EAGAIN (queue is full, and IPC_NOWAIT was asserted) EACCES (permission denied, no write permission) EFAULT (msgp address isn't accessable - invalid) EIDRM (The message queue has been removed) EINTR (Received a signal while waiting to write) EINVAL (Invalid message queue identifier, nonpositive message type, or invalid message size) ENOMEM (Not enough memory to copy message buffer) NOTES:
msgflg 아규먼트는 0으로 지정될 수 있다.(ignored), or:
int send_message( int qid, struct mymsgbuf *qbuf ) { int result, length; /* 길이는 기본적으로 구조체의 크기 - mtype의 크기 이다. */ length = sizeof(struct mymsgbuf) - sizeof(long); if((result = msgsnd( qid, qbuf, length, 0)) == -1) { return(-1); } return(result); }
#include <stdio.h> #include <stdlib.h> #include <linux/ipc.h> #include <linux/msg.h> main() { int qid; key_t msgkey; struct mymsgbuf { long mtype; /* 메세지 타입 */ int request; /* 작업 요청 번호 */ double salary; /* 직원의 급여 */ } msg; /* IPC 키 값을 발생시킨다 */ if(( qid = open_queue( mdgkey)) == -1) { perror("open_queue"); exit(1); } /* 임의의 테스트 자료를 메세지에 적재한다 */ msg.mtype = 1; /* 메세지 타입은 양수여야 한다 */ msg.request = 1; /* 자료 요소 #1 */ msg.salary = 1000.00; /* 자료 요소 #2 (나의 연간 급여) */ /* 뻥 날려보낸다 */ if((send_message( qid, &msg )) == -1) { perror("send_message"); exit(1); } }
현재 우리는 큐에 메세지를 가지고 있으며, 큐의 상태를 보기위해 ipcs 명령어를 사용해라. 큐로 부터 실제로 메세지를 조회하기 위한 토론에 들어가 보자. 그런 일을 하기위해 msgrcv() 시스템 호출을 사용한다.:
SYSTEM CALL: msgrcv(); PROTOTYPE: int msgrcv ( int msqid, struct msgbuf *msgp, int msgsz, long mtype, int msgflg ); RETURNS: Number of bytes copied into message buffer -1 on error: errno = E2BIG (Message length is greater than msgsz, no MSG_NOERROR) EACCES (No read permission) EFAULT (Address pointed to by msgp is invalid) EIDRM (Queue was removed during retrieval) EINTR (Interrupted by arriving signal) EINVAL (msgqid invalid, or msgsz less than 0) ENOMSG (IPC_NOWAIT asserted, and no message exists in the queue to satisfy the request) NOTES:
msgsz = sizeof(struct mymsgbif) - sizeof(long);
IPC_NOWAIT가 flag처럼 넘겨지고 이용가능한 메세지가 없으면, 호출한 프로세스에게 ENOMSG를 반환한다. 그렇지 않으면, 호출한 프로세스는 msgrcv() 파리미터를 만족시키는 메세지가 큐에 도착할 때까지 기다린다. 클라이언트가 메세지를 기다리고 있는 동안 큐가 지워지면, EIDRM이 반환된다. 프로세스가 차단 상태에 있거나 메세지가 도착하기를 기다리는 동안 신호가 잡히면, EINTR가 반환된다.
큐로 부터 메세지를 조회하는 빠른 wrapper 함수를 점검해 보자.:
int read_message( int qid, long type, struct mymsgbuf *qbuf ) { int result, length; /* 크기는 기본적으로 구조체의 크기 - mtype의 크기 이다. */ length = sizeof(struct mymsgbuf) - sizeof(long); if((result = msgrcv( qid, qbuf, length, type, 0)) == -1) { return(-1); } return(result); }큐로 부터 메세지의 조회가 성공적으로 이루어지면, 큐 안에 있는 메세지는 파괴된다.
msgflg 아규먼트 안의 MSG_NOERROR 비트는 몇몇의 부가적인 능력을 제공한다. 물리적인 메세지 자료의 크기가 msgsz보다 크고 MSG_NOERROR가 사용되면, 메세지는 잘려져 오직 msgsz 바이트만큼만 반환된다. 일반적으로 msgrcv() 시스템 호출은 -1(E2BIG)을 반환하고 다음의 조회를 위해 큐 상에 메세지를 남겨 놓는다. 이런 동작은 우리의 요청에 만족하는 메세지가 도착했는지를 알아보기 위해 우리가 큐 안을 엿볼(peek) 수 있는 또 다른 wrapper 함수를 만들어 사용할 수 있다.
int peek_message( int qid, long type ) { int result, length; if((result = msgrcv( qid, NULL, 0, type, IPC_NOWAIT)) == -1) { if(errno == E2BIG) return(TRUE); } return(FALSE); }
Copyright (c) 1996,1997 by Euibeom.Hwang & SangEun.Oh All Rights Reserved
Email To:Webmaster ,
Another address
LAST UPDATE Nov 18,1997
Created Nov 17,1997