全部博文(71)
分类: LINUX
2008-04-16 09:35:20
4.
名称:: |
msgrcv |
功能: |
从队列中取出消息 |
头文件: |
#include #include #inlcude |
函数原形: |
int msgrcv(int msqid, struct msgbuf *msgp, int msgsz, long msgtyp, int msgflg); |
参数: |
msqid 消息队列描述字 msgp 指向消息数据的指针 msgsz 接收消息的大小 msgtyp 请求读取的消息类型 msgflg 标志位 |
返回值: |
若成功则为消息数据部分的长度,若出错则为-1。 |
该系统调用从msgid代表的消息队列中读取一个消息,并把消息存储在msgp指向的msgbuf结构中。
msqid为消息队列描述字;消息返回后存储在msgp指向的地址,msgsz指定msgbuf的mtext成员的长度(即消息内容的长度),msgtyp为请求读取的消息类型;读消息标志msgflg可以为以下几个常值的或:
IPC_NOWAIT 如果没有满足条件的消息,调用立即返回,此时,errno=ENOMSG
IPC_EXCEPT 与msgtyp>0配合使用,返回队列中第一个类型不为msgtyp的消息
IPC_NOERROR 如果队列中满足条件的消息内容大于所请求的msgsz字节,则把该消息截断,截断部分将丢失。
msgtyp使我们可以指定想要哪一种消息:
msgtyp==0 返回队列中的第一个消息。
msgtyp>0 返回队列中消息类型为msgtyp的第一个消息。
msgtyp<0 返回队列中消息类型值小于或等于msgtyp绝对值的消息,如果这种消息有若干个,则取类型值最小的消息。
当msgrcv成功返回,与消息队列相关的msqid_ds结构得到更新,以标明发出该调用的进程ID(msg_lspid),进行该调用的时间(msg_stime),并将队列中消息数(msg_qnum)减1。
7.消息队列与管道以及有名管道的比较
消息队列与管道以及有名管道相比,具有更大的灵活性,首先,它提供有格式字节流,有利于减少开发人员的工作量;其次,消息具有类型,在实际应用中,可作为优先级使用。这两点是管道以及有名管道所不能比的。同样,消息队列可以在几个进程间复用,而不管这几个进程是否具有亲缘关系,这一点与有名管道很相似;但消息队列是随内核持续的,与有名管道(随进程持续)相比,生命力更强,应用空间更大。
输出消息队列信息的例子:
#include #include #include #define KEY 75 void msg_stat(int,struct msqid_ds); int main() { int msgid; int sflags,rflags; struct msqid_ds msg; struct msgbuf{ int mtypes; char mtext[10]; }msg_buf; msgid=msgget(KEY,IPC_CREAT); msg_stat(msgid,msg); sflags=IPC_NOWAIT; msg_buf.mtypes=10; msg_buf.mtext[0]=’a’; msgsnd(msgid,&msg_buf,sizeof(msg_buf.mtext),sflags); msg_stat(msgid,msg); rflags=IPC_NOWAIT|MSG_NOERROR; msgrcv(msgid,&msg_buf,4,10,rflags); msg.msg_perm.uid=8; msg.msg_perm.gid=8; msg.msg_qbytes=16388; msgctl(msgid,IPC_SET,&msg); msg_stat(msgid,msg); msgctl(msgid,IPC_RMID,NULL); } void msg_stat(int msgid,struct msqid_ds msg) { msgctl(msgid,IPC_STAT,&msg); printf("current number of bytes on queue is %d\n",msg_info.msg_cbytes); /*最后消息的类型*/ printf("number of messages in queue is %d\n",msg_info.msg_qnum);/*当前消息队列的消息数*/ printf("max number of bytes on queue is %d\n",msg_info.msg_qbytes); /*消息队列的容量*/ printf("pid of last msgsnd is %d\n",msg_info.msg_lspid);/*最后发送消息时间*/ printf("pid of last msgrcv is %d\n",msg_info.msg_lrpid); /*最后接受消息进程*/ printf("last msgsnd time is %s", ctime(&(msg_info.msg_stime)));/*最后发送消息时间*/ printf("last msgrcv time is %s", ctime(&(msg_info.msg_rtime)));/*最后接受消息时间*/ printf("last change time is %s", ctime(&(msg_info.msg_ctime)));/* 最后修改时间*/ printf("msg uid is %d\n",msg_info.msg_perm.uid); /*进程id*/ printf("msg gid is %d\n",msg_info.msg_perm.gid); /*进程组id*/ } |
用消息队列实现进程间通信的例子:
/* 14_6.c客户进程*/ #include #define MAXLINE 100
long mtype; /*消息类型*/ pid_t pid; /*消息发送进程ID */ void client() fgets(msg.mtext,MAXLINE,stdin);/*把用户输入读入缓冲区*/ struct msgform long mtype; pid_t pid; /*输出消息*/ while(msg.mtype!=5); |
程序client.c和server.c,分别用于消息的发送与接收.server建立一个 Key 为75的消息队列,等待其它进程发来的消息。当遇到类型为1的消息,则作为结束信号,取消该队列,并退出server。server每接收到一个消息后显示一句“server:输入信息”. client使用 key为75的消息队列,先后发送类型从3到1的消息,然后退出。最后一个消息,即是 server端需要的结束信号。client 每发送一条消息后显示一句 “client:要发送的消息”。
注意: 二个程序分别编辑、编译为client与server。执行:
./server&
./client