1. 消息队列

1)消息队列由消息队列ID来唯一标识。

2)消息队列就是一个消息的列表。用户可以在消息队列中添加消息、读取消息等。

3)消息队列可以按照类型来发送/接收消息。

4)消息队列的操作包括创建或打开消息队列、添加消息、读取消息和控制消息队列。

5)创建或打开消息队列使用的函数是msgget,这里创建的消息队列的数量会受到系统消息队列数量的限制。

6) 添加消息使用的函数msgsnd,按照类型把消息添加到已打开的消息队列末尾。

7)读取消息使用的函数是msgrcv,可以按照类型把消息从消息队列中取走。

8)控制消息队列使用的函数msgctl

 

2. 消息队列结构

IPC对象之消息队列

 

3. 消息队列编程

使用消息队列通常需要创建/打开消息队列、添加消息、读取消息、控制消息队列四种操作。

 

1)创建/打开消息队列

函数msgget()

头文件:#include<sys/types.h>

              #include<sys/ipc.h>

              #include<sys/msg.h>

函数原型:int msgget(key_t key,int msgflg)

函数参数:key            消息队列的键值,其他进程通过该值访问该消息队列,其中有个特殊值IPC_PRIVATE,表示创建当前进程的私有消息队列

              msgflg    同open()函数的第三个参数,为消息队列设定权限,通常使用八进制表示。

函数返回值:成功:消息队列ID

                  失败:-1

 

2)向消息队列的末尾添加消息

函数msgsnd()

头文件:#include<sys/types.h>

              #include<sys/ipc.h>

              #include<sys/msg.h>

函数原型:int msgsnd(int msqid, const void*msgp, size_t msgsz, int msgflg)

函数参数:msqid 消息队列标识符(即msgget()函数的返回值)

                msgp 指向消息队列的结构体指针,必须使用地址传递的方式传参。该结构体的常用类型如下:

                     structmsgbuf

                     {

                            longmtype;//消息类型,必须大于0

                            charmtext[n];//消息正文

                     };

              msgsz    消息正文的字节数,必须与第二个参数的消息正文数据长度一致

              msgflg

                     IPC_NOWAIT 若消息无法立即发送则立即返回

                     0                   若消息无法立即发送则阻塞等待消息发送成功

函数返回值:成功:0

                  失败:-1

 

3)读取消息队列

函数msgrcv()

头文件:#include<sys/types.h>

              #include<sys/ipc.h>

              #include<sys/msg.h>

函数原型:ssize_t msgrcv(int msqid, const void*msgp, size_t msgsz, long msgtyp, int msgflg)

函数参数:

               msqid   消息队列标识符(即msgget()函数的返回值)

               msgp  指向消息队列的结构体指针,必须使用地址传递的方式传参。该结构体的类型同上

              msgsz    消息正文的字节数,必须与第二个参数的消息正文数据长度一致

              msgtyp  

                     0            接收消息队列中第一个消息

                     大于0    接收消息队列中第一个值为msgtyp的消息

                     小于0    接收消息队列中具有小于或等于msgtyp绝对值的最小mtype值的第一条消息

              msgflg

                     MSG_NOERROR    若返回的消息比msgsz字节多,则消息会截断到msgsz字节,且不通知消息发送进程

                     IPC_NOWAIT 若消息队列中无对应类型的消息接收则立即返回

                     0                   阻塞等待直至接收到一条相应类型的消息为止

函数返回值:

              成功:0

              失败:-1

 

4)控制消息队列包括获得属性、删除消息队列等

函数msgctl()

头文件:#include<sys/types.h>

              #include<sys/ipc.h>

              #include<sys/msg.h>

函数原型:int msgctl(int msqid, int cmd, structmsqid_ds *buf)

函数参数:

              msqid     消息队列标识符(即msgget()函数的返回值)

              cmd       需要对消息队列采取的操作。可取值有很多,

常用的有:

              IPC_STAT       读取消息队列的数据结构msqid_ds并将其存储在buf指定的地址中

              IPC_SET         设置消息队列中的数据结构msqid_ds中的pic_perm元素的值。这个值来自buf参数

              IPC_RMID      从内核中删除消息队列

              buf         该参数是一个msqid_ds类型的结构体指针,使用时必须使用地址传递的方式。结构体成员很多,常用的有:

                     structmsqid_ds

                     {

                            uid_tmsg_perm.uid;    /* Effective UID of owner*/

                            gid_tmsg_perm.gid;    /* Effective GID of owner*/

                            ……

                     };

函数返回值:

              成功:0

              失败:-1

 

示例代码分为两个文件,写消息队列和读消息队列。

文件一,写消息队列代码:

/*************************************************************************

 @Author: wanghao

 @Created Time : Wed 23 May 2018 06:06:21 AMPDT

 @File Name: msg_snd_demo.c

 @Description:

 ************************************************************************/

#include <string.h>

#include <stdio.h>

#include <stdlib.h>

#include <sys/msg.h>

 

typedef struct{

       longtype;

       intstart;

       intend;

}MSG;

 

int main(int argc,char *argv[])

{

       if(argc <2){

              printf("usage:%s key\n",argv[0]);

              exit(1);

       }

       key_tkey = atoi(argv[1]);

       printf("key:%d\n",key);

 

       intmsq_id;

       if((msq_id= msgget(key,IPC_CREAT|IPC_EXCL|0777))<0){

              perror("msggeterror");

       }

      

       printf("msqid: %d\n",msq_id);

 

       MSG m1 = {4,4,400};

       MSGm2 = {2,2,200};

 

       MSG m3 = {1,1,100};

       MSG m4 = {6,6,600};

       MSGm5 = {6,60,6000};

 

       if(msgsnd(msq_id,&m1,sizeof(MSG)-sizeof(long),IPC_NOWAIT)<0){

              perror("msgsnderror");

       }

 

 

       if(msgsnd(msq_id,&m2,sizeof(MSG)-sizeof(long),IPC_NOWAIT)<0){

              perror("msgsnderror");

       }

       if(msgsnd(msq_id,&m3,sizeof(MSG)-sizeof(long),IPC_NOWAIT)<0){

              perror("msgsnderror");

       }

       if(msgsnd(msq_id,&m4,sizeof(MSG)-sizeof(long),IPC_NOWAIT)<0){

              perror("msgsnderror");

       }

       if(msgsnd(msq_id,&m5,sizeof(MSG)-sizeof(long),IPC_NOWAIT)<0){

              perror("msgsnderror");

       }

 

       structmsqid_ds ds;

       if(msgctl(msq_id,IPC_STAT,&ds)< 0){

              perror("msgctlerror");

       }

       printf("msgtotal: %ld\n",ds.msg_qnum);

 

       exit(0);

}

文件二,读取消息队列代码:

/*************************************************************************

 @Author: wanghao

 @Created Time : Wed 23 May 2018 06:03:25 AMPDT

 @File Name: msg_rcv_demo.c

 @Description:

 ************************************************************************/

#include <sys/msg.h>

#include <string.h>

#include <stdio.h>

#include <stdlib.h>

 

typedef struct{

       longtype;

       intstart;

       intend;

}MSG;

 

int main(int argc, char *argv[])

{

       if(argc< 3){

              printf("usage:%s key type\n",argv[0]);

              exit(1);

       }

       key_tkey = atoi(argv[1]);

       longtype = atoi(argv[2]);

 

       intmsq_id;

       if((msq_id= msgget(key,0777)) < 0){

              perror("msggeterror");

       }

 

       printf("msgid: %d\n",msq_id);

 

       MSGm;

       if(msgrcv(msq_id,&m,sizeof(MSG)-sizeof(long),type,IPC_NOWAIT)<0){

              perror("msgrcverror");

       }else{

              printf("type:%ld start: %d end: %d\n",m.type,m.start,m.end);

       }

      

       structmsqid_ds ds;

       if(msgctl(msq_id,IPC_STAT,&ds)< 0){

              perror("msgctlerror");

       }

       if(ds.msg_qnum== 0)

       {

              msgctl(msq_id,IPC_RMID, NULL);

       }

      

       exit(0);

}



 

 

 


相关文章: