系统性红斑狼疮紫癜:利用消息队列实现进程间通信

来源:百度文库 编辑:中财网 时间:2024/05/05 19:26:00
所谓消息功能,是指由一个进程产生并送出的消息,被放在一个叫做“消息队列”的列中管理,然后由接收方从消息队列中取出消息,这么一种功能。(先入先出)

做一个例子程序看看:
下面的两个程序分为发送方和接收方。发送方将自己的PID和从标准输入输入的一个字符串送至消息队列,接收方把消息队列中所有的PID和字符串读出,并输出至标准输出。

/*       msend.c */
#include
#include
#include
#include

int      main()
{
         int      msqid;
         key_t    msgkey;
         struct   msgbuf
         {
                 long     mtype;
                 char     mdata[256];
         };
         struct   msgbuf   msgdata , *p ;
        
         p = &msgdata ;
         printf("Enter message : ");
         fflush( stdin );         /*       刷新标准输入缓冲区       */

         gets( p->mdata );        /*       输入字符串       */
         p->mtype = getpid();
         msgkey = ftok ( "mrecv" , 'a' );         /*       计算标识符       */
         msqid = msgget( msgkey , IPC_CREAT | 0666 ) ;    /*       建立消息队列     */
         msgsnd( msqid , p , sizeof(p->mdata) , 0 );      /*       送消息   */
         return 0;
}

/*       mrecv.c */
#include
#include
#include
#include

int      main()
{       
         int      msqid;
         key_t    msgkey;
         struct   msgbuf
         {
                 long     mtype;
                 char     mdata[256];
         };
         struct   msgbuf   msgdata , *p ;
         p = &msgdata ;
         msgkey = ftok( "mrecv" , 'a' );          /*       计算标识符       */
         msqid = msgget( msgkey , IPC_CREAT | 0666 ) ;    /*       取得消息队列的ID         */
         while(1)
         {
                 msgrcv( msqid , p , sizeof(p->mdata) , 0 , 0 ) ;         /*       读消息   */
                 printf("Message received from %ldn%sn" , p->mtype , p->mdata );
         }
         return 0;
}
                
执行例:
% msend
Enter message : Hello , world
%msend
Enter message : I am Syuu I

%mrecv
Message received from 321
Hello , world
Message received from 326
I am Syuu I

使用消息功能,可分如下几步
发送方:
1.生成消息队列,取得ID。
2.向消息队列送消息。
接收方:
1.根据标识符,取得ID。
2.从消息队列接收消息。
3.删除消息队列。

例程序相对来说比较简单。我们就不解释了。

消息队列的使用方法以及函数的构造等等基本上和上一章所讲的共享内存的使用方法一样。可参考上一章来理解本章内容。
说说出现的函数:

#include
#include
#include

int      msgget( key_t msgkey , int flag );
取得一个消息队列的ID,如不存在则建立。
返回值:         成功时:消息队列的ID
                 失败时:-1

int      msgsnd( int msqid , struct msgbuf *msgp , size_t msgsiz , int msgflag );
向消息队列送消息
返回值:         成功时:0
                 失败时:-1
msqid是消息队列的ID,size_tmsgsiz是结构体成员mdata的大小,msgflag与上一章所讲的共享内存的flag起一样的作用,不过,当这个参数为IPC_NOWAIT的时候,如果消息队列已满,则返回错误值。如果不为IPC_NOWAIT,在消息队列已满 的情况下,会一直等到消息队列有空地方的时候再发送。
注意这里的这个 struct msgbuf *msgp 。要求的格式如下:
struct   msgbuf
{
         long     mtype;
         char     mdata[256];
};
longmtype在这里我们用来保存本进程的PID。mdata则是保存要发送的数据。由于mdata的大小不一定(根据实际需要定义),所以这个结构体并没有事先定义好。但是我们定义这个结构体的时候一定要遵循这个规定。你可以改的,只有mdata的大小,和结构体的名称。尽量不要修改结构体成员的名称和类型。实际上,根据mtype,我们还可以有所选择地接受消息。这在下面将会谈到。

int      msgrcv( int msqid , struct msgbuf *msgp , size_t msgsiz , long msgtyp , int msgflag );
从消息队列取得一个消息
返回值:         成功时:0
                 失败时:-1
msqid , *msgp , msgsiz不用说了。longmsgtyp是结构体msgbuf的mtype成员。msgflag与上述一样。只不过为IPC_NOWAIT的时候,如果消息队列是空的,则等到有消息可读的时候再读。当不为IPC_NOWAIT的时候,如果消息队列是空的,则返回错误值(与字面上理解的有些相反)

同样地,为了控制管理消息队列,一样有一个函数msgctl()如下:
#include
#include
#include

int      msgctl( int msqid , int cmd , struct msqid_ds *buf );
返回值:         成功时:0
                 失败时:-1
cmd所指定的值与共享内存部分相同。