5.2 SYSV进程通信之消息队列

1 /*linux下进程间通信的几种主要手段简介:
 2  *
 3  *(进程间)管道(Pipe)及有名管道(named pipe):管道可用于具有亲缘关系进程间的通信,有名管道克服了管道没有
 4  *         名字的限制,因此,除具有管道所具有的功能外,它还允许无亲缘关系进程间的通信;
 5  *(进程/线程间)信号(Signal):信号是比较复杂的通信方式,用于通知接受进程有某种事件发生,
 6  *         除了用于进程间通信外,进程还可以发送信号给进程本身;linux除了支持Unix早期信号语义函数sigal外,
 7  *         还支持语义符合Posix.1标准的信号函数sigaction(实际上,该函数是基于BSD的,BSD为了实现可靠信号机制,
 8  *         又能够统一对外接口,用sigaction函数重新实现了signal函数);
 9  *
10  * (进程间)消息队列:消息队列是消息的链接表,包括Posix消息队列system V消息队列。
11  *         有足够权限的进程可以向队列中添加消息,被赋予读权限的进程则可以读走队列中的消息。
12  *         消息队列克服了信号承载信息量少,管道只能承载无格式字节流以及缓冲区大小受限等缺点。
13  * (进程间)共享内存:使得多个进程可以访问同一块内存空间,是最快的可用IPC形式。
14  *         是针对其他通信机制运行效率较低而设计的。往往与其它通信机制,如信号量结合使用,
15  *         来达到进程间的同步及互斥。
16  * (进程/线程间)信号量(semaphore):主要作为进程间以及同一进程不同线程之间的同步手段。
17  *
18  * ////套接口(Socket):更为一般的进程间通信机制,可用于不同机器之间的进程间通信。
19  *         起初是由Unix系统的BSD分支开发出来的,但现在一般可以移植到其它类Unix系统上:
20  *         Linux和System V的变种都支持套接字。
21  * */

ftok.c

22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <error.h>
25 #include <errno.h>
26 #include <sys/types.h>
27 #include <sys/ipc.h>
28 
29 #define error_exit(_errmsg_) error(EXIT_FAILURE,errno,_errmsg_)
30 
31 int main()
32 {
33     /*根据一个pathname和project_id 产生一个SYSV IPC 对象的键值
34      * key_t ftok(const char *pathname, int proj_id);
35      * 参数:
36      *成功返回键值,失败返回-1
37      * */
38     key_t key;
39     if(-1 == (key = ftok(".",'a')))
40 /*    {
41         perror("fail to ftok!");
42         return -1;
43     }
44 */    
45         error_exit("fail to ftok!");
46     
47     printf("key = %#x\n",key);
48 
49 
50     return 0;
51 }

msg.c

 1 /*进程间通信(IPC/Inter-Process Communication ),指至少两个进程 或线程 间传送数据或信号的一些技术或方法。
 2  *        进程是计算机系统 分配资源的最小单位。每个进程都有自己的一部分独立的系统资源,彼此是隔离的。
 3  *    为了能使不同的进程互相访问资源并进行协调工作,才有了进程间通信。这些进程 可以运行在同一计算机上或网络连接的不同计算机上。 进程间通信技术包括消息传递、同步、共享内存和远程过程调用 。 IPC是一种标准的Unix 通信机制。
 4  *IPC三种通信机制是指:信号量、共享内存、消息队列
 5  *    信号量:通过操作系统中的PV操作来实现;
 6      共享内存:申请一块内存,进程A往共享内存中写,其他的进程就可以通过读出共享内存中的内容来获取进程A所传送的信息;
 7      消息队列:创建一个消息队列,进程A往队列里面写,那么进程B通过读队列中的容来获取进程A传送的信息。
 8 
 9  *     消息队列:创建一个消息队列,进程A往队列里面写,那么进程B通过读队列中的容来获取进程A传送的信息。
10  * */
11 #include <sys/types.h>
12 #include <sys/ipc.h>
13 #include <sys/msg.h>
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <string.h>
17 #include <error.h>
18 #include <errno.h>
19 
20 #define error_exit(_errmsg_)    error(EXIT_FAILURE, errno, _errmsg_)
21 
22 typedef struct msg
23 {
24     long type;
25     char mtext[256];
26 }MSG;
27 
28 int main(void)
29 {
30     key_t key;
31     if (-1 == (key = ftok(".", 'a')))    /*1.ftok产生键值*/
32         error_exit("fail to ftok");
33     /* 创建/打开一个消息队列
34      * int msgget(key_t key, int msgflg);
35      * 参数:
36      *     key:键值/关键字
37      *     msgflg: IPC_CREAT: 创建一个消息队列
38      *             IPC_EXCL:  检测是否创建该key值对应的消息队列
39      *     成功返回0;失败返回-1
40      * */
41     int msgid;
42     if (-1 == (msgid = msgget(key, IPC_CREAT | 0644)))/*2.创建/打开一个消息队列 产生消息队列的ID号*/
43         error_exit("fail to msgget");
44     
45     MSG message;
46     MSG ret;
47     message.type = 666;
48     strcpy(message.mtext, "hello world!");    /*3.使用*/
49     
50     /*向一个消息队列发送一条消息
51      *int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
52      *参数:
53          msqid:消息队列ID号
54          msgp: 要发送消息空间的首地址
55          msgsz:发送消息中数据的大小
56          msgflg:消息对类的属性/决定消息队列是否阻塞:0 阻塞;IPC_NOWAIT 不阻塞
57      
58      *从消息队列中读取消息
59      *ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp,int msgflg);
60      *参数:
61          msqid:消息队列ID号
62          msgp: 存放读取消息的空间首地址
63          msgsz:消息中数据的大小
64          msgtype: 消息类型
65          msgflg:消息对类的属性/决定消息队列是否阻塞:0 阻塞;IPC_NOWAIT 不阻塞
66      * */
67 
68     if (-1 == msgsnd(msgid, &message, sizeof(MSG) - sizeof(long), 0))/*4.发消息*/
69         error_exit("fail to msgsnd");
70     
71     getchar();
72 
73     if (-1 == msgrcv(msgid, &ret, sizeof(MSG) - sizeof(long), 666, 0))/*5.接受消息*/
74         error_exit("fail to msgrcv");
75 
76     printf("ret.mtext = %s\n", ret.mtext);
77     return 0;
78 }

msg_msgctl.c

 1 /*SYSV进程通信 之 消息队列
 2  *
 3  * */
 4 #include <stdio.h>
 5 #include <stdlib.h>
 6 #include <string.h>
 7 #include <error.h>
 8 #include <errno.h>
 9 #include <sys/types.h>
10 #include <sys/ipc.h>
11 #include <sys/msg.h>
12 
13 #define error_exit(_errmsg_) error(EXIT_FAILURE,errno,_errmsg_)
14 
15 int main()
16 {
17     key_t key;
18     if(-1 == (key = ftok(".",'a')))
19         error_exit("fail to ftok!");
20     /* 创建/打开一个消息队列
21      * int msgget(key_t key, int msgflg);
22      * 参数:
23      *     key:键值
24      *     msgflg:IPC_CREAT 如果消息队列对象不存在,则创建之,存在则进行打开操作;
25      *             IPC_EXCL 检测是否创建该键值对应的消息队列/
26      *                     和IPC_CREAT 一起使用(用”|”连接),如果消息对象不存在则创建之,否则产生一个错误并返回.     
27      * 成功返回消息队列ID号,失败返回-1
28      *
29      * */
30     int msgid = 0;
31     if(-1 == (msgid = msgget(key,IPC_CREAT | 0644)))
32         error_exit("fail to msgget!");
33 
34     /*给一个消息队列发送一个控制命令
35      *int msgctl(int msqid, int cmd, struct msqid_ds *buf);
36      *参数:
37 msgid:消息队列的ID号
38 cmd:
39     IPC_STAT:获得消息队列的状态//取出系统保存的消息队列的msqid_ds 数据,并将其存入参数buf 指向的msqid_ds 结构
40     IPC_SET:设置消息队列的属性//设定消息队列的msqid_ds 数据中的msg_perm 成员。设定的值由buf 指向的msqid_ds
41     IPC_RMID:删除消息队列
42         buf:指向结构体msqid_ds
43         成功返回0;失败返回-1
44      * */
45 
46     struct msqid_ds buff;
47     if(-1 == msgctl(msgid,IPC_STAT,&buff))
48     error_exit("fail to msgctl!");
49     printf("buff = %d\n",buff.msg_qbytes);
50 
51     if(-1 == msgctl(msgid,IPC_RMID,&buff))
52     error_exit("fail to msgctl!");
53     
54     printf("key = %#x\n",key);
55 
56     return 0;
57 }

 

posted @ 2017-03-14 21:34  bkycrmn  阅读(292)  评论(0)    收藏  举报