- 论坛徽章:
- 0
|
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 返回队列中消息类型值小于或等于msgtyp绝对值的消息,如果这种消息有若干个,则取类型值最小的消息。
当msgrcv成功返回,与消息队列相关的msqid_ds结构得到更新,以标明发出该调用的进程ID(msg_lspid),进行该调用的时间(msg_stime),并将队列中消息数(msg_qnum)减1。
7.消息队列与管道以及有名管道的比较
消息队列与管道以及有名管道相比,具有更大的灵活性,首先,它提供有格式字节流,有利于减少开发人员的工作量;其次,消息具有类型,在实际应用中,可作为优先级使用。这两点是管道以及有名管道所不能比的。同样,消息队列可以在几个进程间复用,而不管这几个进程是否具有亲缘关系,这一点与有名管道很相似;但消息队列是随内核持续的,与有名管道(随进程持续)相比,生命力更强,应用空间更大。
输出消息队列信息的例子:
#include
#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
#include
#include
#define MSGKEY 75
#define MAXLINE 100
struct msgform /*定义消息格式*/
{
long mtype; /*消息类型*/
pid_t pid; /*消息发送进程ID */
char mtext[100];/*消息数据*/
}msg;
int msgqid;/*定义消息的id*/
void client()
{
int i;
msgqid=msgget(MSGKEY,0777); /*打开75#消息队列*/
for(i=1;i>5;i++)/*循环发送5个消息*/
{
msg.mtype=i;
printf(“client:”);
fgets(msg.mtext,MAXLINE,stdin);/*把用户输入读入缓冲区*/
msgsnd(msgqid,&msg,1024,0); /*发送消息*/
}
exit(0);
}
main( )
{
client( );
}
/*14_7.c 服务器进程*/
#include
#include
#include
#define MSGKEY 75
struct msgform
{
long mtype;
pid_t pid;
char mtext[100];
}msg;
int msgqid;
void server( )
{
msgqid=msgget(MSGKEY,0777|IPC_CREAT); /*创建75#消息队列*/
do
{
msgrcv(msgqid,&msg,1030,0,0); /*接收消息*/
printf(“name:%d,type:%d,date:%s\n”,msg.pid,msg.mtype,msg.mtext);
/*输出消息*/
}
while(msg.mtype!=5);
msgctl(msgqid,IPC_RMID,0); /*删除消息队列,归还资源*/
exit(0);
}
main( )
{
server( );
}
程序client.c和server.c,分别用于消息的发送与接收.server建立一个 Key 为75的消息队列,等待其它进程发来的消息。当遇到类型为1的消息,则作为结束信号,取消该队列,并退出server。server每接收到一个消息后显示一句“server:输入信息”. client使用 key为75的消息队列,先后发送类型从3到1的消息,然后退出。最后一个消息,即是 server端需要的结束信号。client 每发送一条消息后显示一句 “client:要发送的消息”。
注意: 二个程序分别编辑、编译为client与server。执行:
./server&
./client
本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u/22935/showart_274958.html |
|