消息队列再整理
ftok()
#include <sys/types.h>
#include <sys/ipc.h>
函数原型:
key_t ftok( const char * pathname , int proj_id );
参数:
pathname 就时你指定的文件名(该文件必须是存在而且可以访问的),id是子序号,虽 然为int,但是只有8个比特被使用(0-255)。
返回值: 成功时候返回key_t 类型的key值,失败返回-1
msgget
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
函数原型: int msgget ( key_t key , int msgflg );
函数描述:建立消息队列
参数:
msgget()函数的第一个参数是消息队列对象的关键字(key),函数将它与已有的消息队
列对象的关键字进行比较来判断消息队列对象是否已经创建。而函数进行的具体操作是
由第二个参数,msgflg 控制的。它可以取下面的几个值:
IPC_CREAT :如果消息队列对象不存在,则创建之,否则则进行打开操作;
IPC_EXCL:和IPC_CREAT 一起使用(用”|”连接),如果消息对象不存在则创建之,否 则产生一个错误并返回。
返回值:
成功时返回队列ID,失败返回-1,错误原因存于error中
EEXIST (Queue exists, cannot create)
EIDRM (Queue is marked for deletion)
ENOENT (Queue does not exist)
ENOMEM (Not enough memory to create queue)
ENOSPC (Maximum queue limit exceeded)
msgsnd函数:将消息送入消息队列
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h
函数原型:int msgsnd ( int msgid , struct msgbuf*msgp , int msgsz, int msgflg );
参数说明:
传给msgsnd()函数的第一个参数msqid 是消息队列对象的标识符(由msgget()函数得
到),第二个参数msgp 指向要发送的消息所在的内存,第三个参数msgsz 是要发送信息 的长度(字节数),可以用以下的公式计算:
msgsz = sizeof(struct mymsgbuf) - sizeof(long);
第四个参数是控制函数行为的标志,可以取以下的值:
0,忽略标志位;
IPC_NOWAIT,如果消息队列已满,消息将不被写入队列,控制权返回调用函数的线
程。如果不指定这个参数,线程将被阻塞直到消息被可以被写入。
smgbuf结构体定义如下:
struct smgbuf
{
long mtype;
char mtext [x] ; //长度由msgsz决定
}
msgflg 可设置为 IPC_NOWAIT 。如果消息队列已满或其他情况无法送入消息,则立即 返回 EAGIN
返回: 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)
msgrcv函数:从消息队列中读取消息
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
函数定义:int msgrcv( int msgid , struct msgbuf* msgp , int msgsz , long msgtyp, int msgflg);
参数:
函数的前三个参数和msgsnd()函数中对应的参数的含义是相同的。第四个参数mtype
指定了函数从队列中所取的消息的类型。函数将从队列中搜索类型与之匹配的消息并将
之返回。不过这里有一个例外。如果mtype 的值是零的话,函数将不做类型检查而自动返 回队列中的最旧的消息。第五个参数依然是是控制函数行为的标志,取值可以是:
0,表示忽略;
IPC_NOWAIT,如果消息队列为空,则返回一个ENOMSG,并将控制权交回调用函数
的进程。如果不指定这个参数,那么进程将被阻塞直到函数可以从队列中得到符合条件
的消息为止。如果一个client 正在等待消息的时候队列被删除,EIDRM 就会被返回。如果 进程在阻塞等待过程中收到了系统的中断信号,EINTR 就会被返回。
MSG_NOERROR,如果函数取得的消息长度大于msgsz,将只返回msgsz 长度的信息,
剩下的部分被丢弃了。如果不指定这个参数,E2BIG 将被返回,而消息则留在队列中不 被取出。
当消息从队列内取出后,相应的消息就从队列中删除了。
msgbuf:结构体,定义如下:
struct msgbuf
{
long mtype ; //信息种类
char mtest[x];//信息内容 ,长度由msgsz指定
}
msgtyp: 信息类型。 取值如下:
msgtyp = 0 ,不分类型,直接返回消息队列中的第一项
msgtyp > 0 ,返回第一项 msgtyp与 msgbuf结构体中的mtype相同的信息
msgtyp <0 , 返回第一项 mtype小于等于msgtyp绝对值的信息
msgflg:取值如下:
IPC_NOWAIT ,不阻塞
IPC_NOERROR ,若信息长度超过参数msgsz,则截断信息而不报错。
返回值:
成功时返回所获取信息的长度,失败返回-1,错误信息存于error
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)
例子:
server.c
- <span><strong><em><span style="font-size: small;">#include <stdio.h>
- #include <string.h>
- #include <stdlib.h>
- #include <errno.h>
- #include <unistd.h>
- #include <sys/types.h>
- #include <sys/ipc.h>
- #include <sys/stat.h>
- #include <sys/msg.h>
- #define MSG_FILE "server.c"
- #define BUFFER 255
- #define PERM S_IRUSR|S_IWUSR
- struct msgtype {
- long mtype;
- char buffer[BUFFER+1];
- };
- int main()
- {
- struct msgtype msg;
- key_t key;
- int msgid;
- if((key=ftok(MSG_FILE,'a'))==-1)
- {
- fprintf(stderr,"Creat Key Error:%s\a\n",strerror(errno));
- exit(1);
- }
- if((msgid=msgget(key,PERM|IPC_CREAT|IPC_EXCL))==-1)
- {
- fprintf(stderr,"Creat Message Error:%s\a\n",strerror(errno));
- exit(1);
- }
- while(1)
- {
- msgrcv(msgid,&msg,sizeof(struct msgtype),1,0);
- fprintf(stderr,"Server Receive:%s\n",msg.buffer);
- msg.mtype=2;
- msgsnd(msgid,&msg,sizeof(struct msgtype),0);
- }
- exit(0);
- }</span></em></strong></span>
client.c
- <span><strong><em><span style="font-size: small;">#include <stdio.h>
- #include <string.h>
- #include <stdlib.h>
- #include <errno.h>
- #include <sys/types.h>
- #include <sys/ipc.h>
- #include <sys/msg.h>
- #include <sys/stat.h>
- #define MSG_FILE "server.c"
- #define BUFFER 255
- #define PERM S_IRUSR|S_IWUSR
- struct msgtype {
- long mtype;
- char buffer[BUFFER+1];
- };
- int main(int argc,char **argv)
- {
- struct msgtype msg;
- key_t key;
- int msgid;
- if(argc!=2)
- {
- fprintf(stderr,"Usage:%s string\n\a",argv[0]);
- exit(1);
- }
- if((key=ftok(MSG_FILE,'a'))==-1)
- {
- fprintf(stderr,"Creat Key Error:%s\a\n",strerror(errno));
- exit(1);
- }
- if((msgid=msgget(key,PERM))==-1)
- {
- fprintf(stderr,"Creat Message Error:%s\a\n",strerror(errno));
- exit(1);
- }
- msg.mtype=1;
- strncpy(msg.buffer,argv[1],BUFFER);
- msgsnd(msgid,&msg,sizeof(struct msgtype),0);
- memset(&msg,'\0',sizeof(struct msgtype));
- msgrcv(msgid,&msg,sizeof(struct msgtype),2,0);
- fprintf(stderr,"Client receive:%s\n",msg.buffer);
- exit(0);
- }</span></em></strong></span>