Chinaunix首页 | 论坛 | 博客

分类: 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指定msgbufmtext成员的长度(即消息内容的长度),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结构得到更新,以标明发出该调用的进程IDmsg_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.cserver.c,分别用于消息的发送与接收.server建立一个 Key 75的消息队列,等待其它进程发来的消息。当遇到类型为1的消息,则作为结束信号,取消该队列,并退出serverserver每接收到一个消息后显示一句“server:输入信息”. client使用 key75的消息队列,先后发送类型从31的消息,然后退出。最后一个消息,即是 server端需要的结束信号。client 每发送一条消息后显示一句 “client:要发送的消息
   
注意: 二个程序分别编辑、编译为clientserver。执行:
./server&
./client

阅读(1032) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~