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 }
浙公网安备 33010602011771号