linux ipc—msgqueue

1、概念

消息队列是消息的链表,存放在内存当中,由内核去维护

2、用途

消息队列(也叫做报文队列)能够克服早期unix通信机制的一些缺点。作为早期unix通信机制之一的信号能够传送的信息量有限,后来虽然POSIX 1003.1b在信号的实时性方面作了拓广,使得信号在传递信息量方面有了相当程度的改进。我们可以把消息看作一个记录,具有特定的格式以及特定的优先级。对消息队列有写权限的进程可以向消息队列中按照一定的规则添加新消息;对消息队列有读权限的进程则可以从消息队列中读走消息。消息队列是随内核持续的。

目前主要有两种类型的消息队列:POSIX消息队列以及系统V消息队列,系统V消息队列目前被大量使用。考虑到程序的可移植性,新开发的应用程序应尽量使用POSIX消息队列。

系统V消息队列是随内核持续的,只有在内核重起或者显式删除一个消息队列时,该消息队列才会真正被删除。因此系统中记录消息队列的数据结构(struct ipc_ids msg_ids)位于内核中,系统中的所有消息队列都可以在结构msg_ids中找到访问入口。 消息队列就是一个消息的链表。每个消息队列都有一个队列头,用结构struct msg_queue来描述。队列头中包含了该消息队列的大量信息,包括消息队列键值、用户ID、组ID、消息队列中消息数目等等,甚至记录了最近对消息队列读写进程的ID。读者可以访问这些信息,也可以设置其中的某些信息。

3、特点

7个

①消息队列允许一个或多个进程向它写入或者读取消息,并且每条消息都有类型

②消息队列可以实现消息的随机查询,消息不一定要fifo的顺序,编程时可按消息类型读取

③与管道、命名管道一样,从消息队列中读出消息,消息队列中的数据便会被删除

④只有人工删除或内核重启时,该消息才会被删除,若不人工删除消息队列,该队列会一直存在于内存。

⑤消息队列标识符,来标识消息队列,消息队列在整个系统中时唯一的

⑥消息队列的限制:1、消息队列的个数最多为16个 2、消息队列总容量最多为16384个字节 3、每个消息内容最多为8192字节

4、使用方法

#include <sys/types.h>
 #include <sys/ipc.h>
 key_t ftok(const char *pathname, int proj_id);
 功能:
     获得项目相关的唯一的IPC键值。
 参数:
     pathname:路径名
     proj_id:项目ID,非0整数(只有低8位有效)
 返回值:
     成功返回key值,失败返回 -1。

 

创建消息队列:
 #include <sys/msg.h>
 int msgget(key_t key, int msgflg);
 功能:
  创建一个新的或打开一个已经存在的消息队列。不同的进程调用此函数,只要用相同的key值就能得到同一个消息队列的ID。
 参数:
key:IPC键值
msgflg:标识函数的行为:IPC_CREAT(创建)或IPC_EXCL(如果已经存在则返回失败)。
 返回值:
     成功:消息队列的标识符,失败:返回-1。

消息队列的消息的格式。
typedef struct _msg
 {
  long mtype;  /*消息类型*/
  char mtext[100]; /*消息正文*/
  ... /*消息的正文可以有多个成员*/
 }MSG;
  消息类型必须是长整型的,而且必须是结构体类
 型的第一个成员,类型下面是消息正文,正文可以
 有多个成员(正文成员可以是任意数据类型的)。

 

发送消息:
 #include <sys/msg.h>
 int msgsnd(int msqid, const void *msgp,                        size_t msgsz, int msgflg);
 功能:
     将新消息添加到消息队列。
 参数:
     msqid:消息队列的队列ID。
     msgp:待发送消息结构体的地址。
     msgsz:消息正文的字节数。

 

接收消息:
 #include <sys/msg.h>
 ssize_t msgrcv(int msqid, void *msgp,  size_t        msgsz, long msgtyp, int msgflg);
 功能:
     从ID为msqid的消息队列中接收一个消息。一旦接收消息成功,则消息在消息队列中被删除。
 参数:
msqid:消息队列的ID,代表要从哪个消息列中   获取消息。
msgp: 存放消息结构体的地址。
msgsz:消息正文的字节数。

 

消息队列的控制
 #include <sys/msg.h>
 int msgctl(int msqid, int cmd, struct msqid_ds *buf);
 功能:
     对消息队列进行各种控制,如修改消息队列的属性,或删除消息消息队列。
 参数:
     msqid:消息队列的ID
     cmd:函数功能的控制
     buf:msqid_ds数据类型的地址,用来存放或更改消息队列的属性。

  

 

5、案例

 1 #include <sys/types.h>
 2 #include <sys/stat.h>
 3 #include <fcntl.h>
 4 #include <unistd.h>
 5 #include <stdio.h>
 6 #include <stdlib.h>
 7 #include <sys/ipc.h>
 8 #include <sys/msg.h>
 9 #include <string.h>
10 
11 #ifdef zzl
12 
13 #define M 'z'
14 char writer[]="zzl";
15 
16 #elif defined wss
17 
18 #define M 'w'
19 char writer[]="wss";
20 
21 #elif defined danny
22 #define M 'd'
23 char writer[]="danny";
24 
25 #endif
26 
27 typedef struct _msg
28 {
29  long mtype;
30  char mname[20];
31  char mtext[100];
32 
33 }MSG;
34 
35 int main(int argc, char *argv[])
36 {
37 // key_t key;
38  MSG msg;
39  pid_t pid;
40 
41  char buf[120]="";
42  int msgid;
43 // key=ftok("./",0x01);
44 
45  msgid=msgget((key_t)12345,IPC_CREAT | 0666);
46 
47  pid=fork();
48  if(pid < 0)
49   perror("fork");
50 
51  else if (pid == 0)
52  {
53   while(1)
54   {
55    printf("\r%s:",writer);
56    fflush(stdout);
57    fgets(buf,sizeof(buf),stdin);
58    buf[strlen(buf)-1]='\0';
59    
60    if(buf[0] == 'z' ||buf[0] == 'w' ||buf[0] == 'd')
61    {
62     msg.mtype=(long)buf[0];
63     strcpy(msg.mname,writer);
64     strcpy(msg.mtext,buf+2);
65 
66  if(buf[0] == 'z' ||buf[0] == 'w' ||buf[0] == 'd')
67    {
68     msg.mtype=(long)buf[0];
69     strcpy(msg.mname,writer);
70     strcpy(msg.mtext,buf+2);
71     msgsnd(msgid,&msg,sizeof(MSG)-sizeof(long),0);
72    }
73   }
74  }
75  else if(pid > 0)
76  {
77   while(1)
78   {
79    msgrcv(msgid,&msg,sizeof(MSG)-sizeof(long),(long)(M),0);
80    printf("\rmsg form %s:%s:\n",msg.mname,msg.mtext);
81    printf("\r%s:",writer);
82    fflush(stdout);
83 
84   }
85  }
86 
87 
88  return 0;
89 }

 

 

你可能感兴趣的:(linux)