Linux消息队列
2018-02-04 13:26
162 查看
一、概述
System V三种IPC:消息队列,信号量,共享内存。这三种IPC最先出现AT&T System V UNIX上面,并遵循XSI标准,有时候也称为XSI IPC
本文先探讨消息队列:
1.消息队列允许进程以消息的形式交换数据。读写都是针对整条消息,不能读写消息的一部分,不像管道那样可以以流的形式读写任意字节。
2.消息队列除了数据外,还有一个整数来表示该消息的类型。读取消息的时候即可以按照先进先出方式读取,也可以按照消息类型来读取
二、函数接口
1.创建一个消息队列
#include <sys.msg.h>
int msgget(key_t, int msgflg);
key:是一个整数,该函数会将key转换成一个IPC标识符。key有3种方法定义:1.手动随意指定一个整数。2.把IPC_PRIVATE当作key传入,系统会自动生成。3.用fork()函数。
2.发送消息
#include <sys/msg.h>
int msgsnd(int msgid, const void *msgp, size_t msgsz, int msgflg);
msgqid:用msget()获取的id
msgp:存储消息的结构指针,下面的mtype就是自定义的消息类型,mtext是消息数据
struct msgbuf{
long mtype;
char mtex[1];
}
msgsz:消息的大小,对应上面msgbuf里面的mtext
msgflg:控制消息发送时异常状况,如消息队列满。
3.接收消息
#include <sys/msg.h>
ssize_t msgrcv(int msgid,void *msgp, size_t msgsz, long msgtyp, int msgflg);
msgid:用msget获取的id,或者已知的消息ID。
msgp,msgsz:同msgsnd().
msgtyp:接收消息的类型,即msgbuf里面的mtype.但还有别的用法:
如果为0,就获取队列中第一个可用消息。
大于0,就获取相同类型消息的第一个,mtype.
小于,获取等于或小于mtype的绝对值第一个消息。等会我们做一一做实验
msgflg:同msgsnd()
4.消息控制
#include <sys/msg.h>
int msgctl(int msqid, int cmd, struct msqid_ds *buf);
cmd:有3个选项,IPC_STAT,IPC_SET,IPC_RMID。前2个是获取和设置msgid对应的消息结构体,最后一个是删除消息队列。
三.简单的例子
1.创建消息队列
2.发送消息
3.接收消息
四.实验
1.创建消息,编译执行msg_create.c,用ipcs -q查看消息:
![](https://images2015.cnblogs.com/blog/629717/201601/629717-20160115200731163-932171002.png)
可以看到:msqid就是用IPC_PRIVATE当作key传入,系统会自动生成的,msqid=262144等会接收消息要用。perms是我们代码设置的权限,此时的消息字节和消息数都是0。
2.发送消息,编译执行msg_send.c,并发消息,用ipcs -q查看消息:
![](https://images2015.cnblogs.com/blog/629717/201601/629717-20160115201113569-1037329142.png)
上面./mes_send后面依次是:刚刚创建的消息队列id,消息类型,消息数据。
接下来,我们再继续发送1条1类型消息,2条2类型消息,2条3类型消息,等会接收消息做实验。
![](https://images2015.cnblogs.com/blog/629717/201601/629717-20160115201524100-2139028659.png)
现在我们有6条消息了。
3.接收消息,编译msg_recv.c。我们主要来实验msgrcv()里面的msg_type参数。即该文件的第36行代码。
3.1:当msg_type等于0时,获取队列中第一个可用消息。
![](https://images2015.cnblogs.com/blog/629717/201601/629717-20160115202334741-1118689254.png)
可以看到,1234就是我刚刚第一次发送到该队列的消息。
3.2:当msg_type大于0,获取具有相同类型的第一个消息:
![](https://images2015.cnblogs.com/blog/629717/201601/629717-20160115202700147-99221565.png)
上面我们获取的是3类型的消息,接收的刚好是第一次发送3号消息的haha。
3.3:当msg_type小于0,获取等于或小于msg_type绝对值的第一个消息:
![](https://images2015.cnblogs.com/blog/629717/201601/629717-20160115203032241-1313977626.png)
上面,-3的绝对值是3,而队列中存在最先放进去的消息是1号消息22222(本来是1号的1234,刚刚我们做实验时读取走了,所以剩下它第一)。1小于3,所以1号消息被读取。
4.消息队列的删除,msg_recv.c里面第41行代码,如果放开后编译执行,收到一条消息后整个队列全部删除。
System V三种IPC:消息队列,信号量,共享内存。这三种IPC最先出现AT&T System V UNIX上面,并遵循XSI标准,有时候也称为XSI IPC
本文先探讨消息队列:
1.消息队列允许进程以消息的形式交换数据。读写都是针对整条消息,不能读写消息的一部分,不像管道那样可以以流的形式读写任意字节。
2.消息队列除了数据外,还有一个整数来表示该消息的类型。读取消息的时候即可以按照先进先出方式读取,也可以按照消息类型来读取
二、函数接口
1.创建一个消息队列
#include <sys.msg.h>
int msgget(key_t, int msgflg);
key:是一个整数,该函数会将key转换成一个IPC标识符。key有3种方法定义:1.手动随意指定一个整数。2.把IPC_PRIVATE当作key传入,系统会自动生成。3.用fork()函数。
2.发送消息
#include <sys/msg.h>
int msgsnd(int msgid, const void *msgp, size_t msgsz, int msgflg);
msgqid:用msget()获取的id
msgp:存储消息的结构指针,下面的mtype就是自定义的消息类型,mtext是消息数据
struct msgbuf{
long mtype;
char mtex[1];
}
msgsz:消息的大小,对应上面msgbuf里面的mtext
msgflg:控制消息发送时异常状况,如消息队列满。
3.接收消息
#include <sys/msg.h>
ssize_t msgrcv(int msgid,void *msgp, size_t msgsz, long msgtyp, int msgflg);
msgid:用msget获取的id,或者已知的消息ID。
msgp,msgsz:同msgsnd().
msgtyp:接收消息的类型,即msgbuf里面的mtype.但还有别的用法:
如果为0,就获取队列中第一个可用消息。
大于0,就获取相同类型消息的第一个,mtype.
小于,获取等于或小于mtype的绝对值第一个消息。等会我们做一一做实验
msgflg:同msgsnd()
4.消息控制
#include <sys/msg.h>
int msgctl(int msqid, int cmd, struct msqid_ds *buf);
cmd:有3个选项,IPC_STAT,IPC_SET,IPC_RMID。前2个是获取和设置msgid对应的消息结构体,最后一个是删除消息队列。
三.简单的例子
1.创建消息队列
1 /** 2 * @file msg_create.c 3 */ 4 5 #include <stdio.h> 6 #include <stdlib.h> 7 #include <string.h> 8 #include <sys/msg.h> 9 10 void err_exit(const char *err_msg) 11 { 12 printf("%s error\n", err_msg); 13 exit(1); 14 } 15 16 int main(void) 17 { 18 int msg_id = msgget(IPC_PRIVATE, 0666 | IPC_CREAT); 19 if (msg_id == -1) 20 err_exit("msgget()"); 21 22 printf(" 1561e create msg_id:%d\n", msg_id); 23 24 return 0; 25 }
2.发送消息
1 /** 2 * @file msg_send.c 3 */ 4 5 #include <stdio.h> 6 #include <stdlib.h> 7 #include <string.h> 8 #include <sys/msg.h> 9 10 #define MAX_BUFFER 1024 11 12 typedef struct 13 { 14 long msg_type; 15 char msg_text[MAX_BUFFER]; 16 } msg_t; 17 18 void err_exit(const char *err_msg) 19 { 20 printf("%s error\n", err_msg); 21 exit(1); 22 } 23 24 int main(int argc, char *argv[]) 25 { 26 if (argc < 4) 27 { 28 printf("usage: %s msg_id msg_type msg_text\n", argv[0]); 29 exit(1); 30 } 31 32 int msg_id = atoi(argv[1]); 33 msg_t send_msg; 34 char *text = argv[3]; 35 int text_len = strlen(text); 36 37 send_msg.msg_type = atoi(argv[2]); 38 memcpy((void *)send_msg.msg_text, text, text_len); 39 40 if (msgsnd(msg_id, &send_msg, text_len, 0) == -1) 41 err_exit("msgsnd()"); 42 43 return 0; 44 }
3.接收消息
1 /** 2 * @file msg_recv.c 3 */ 4 5 #include <stdio.h> 6 #include <stdlib.h> 7 #include <string.h> 8 #include <sys/msg.h> 9 10 #define MAX_BUFFER 1024 11 12 typedef struct 13 { 14 long msg_type; 15 char msg_text[MAX_BUFFER]; 16 } msg_t; 17 18 void err_exit(const char *err_msg) 19 { 20 printf("%s error\n", err_msg); 21 exit(1); 22 } 23 24 int main(int argc, const char *argv[]) 25 { 26 if (argc < 3) 27 { 28 printf("usage: %s msg_id msg_type\n", argv[0]); 29 exit(1); 30 } 31 32 int msg_id = atoi(argv[1]); 33 msg_t recv_msg; 34 long msg_type = atoi(argv[2]); 35 36 if (msgrcv(msg_id, &recv_msg, MAX_BUFFER, msg_type, 0) == -1) 37 err_exit("msgrcv()"); 38 39 printf("receive:%s\n", recv_msg.msg_text); 40 41 //if (msgctl(msg_id, IPC_RMID, 0) == -1) 42 // err_exit("msgctl()"); 43 44 return 0; 45 }
四.实验
1.创建消息,编译执行msg_create.c,用ipcs -q查看消息:
![](https://images2015.cnblogs.com/blog/629717/201601/629717-20160115200731163-932171002.png)
可以看到:msqid就是用IPC_PRIVATE当作key传入,系统会自动生成的,msqid=262144等会接收消息要用。perms是我们代码设置的权限,此时的消息字节和消息数都是0。
2.发送消息,编译执行msg_send.c,并发消息,用ipcs -q查看消息:
![](https://images2015.cnblogs.com/blog/629717/201601/629717-20160115201113569-1037329142.png)
上面./mes_send后面依次是:刚刚创建的消息队列id,消息类型,消息数据。
接下来,我们再继续发送1条1类型消息,2条2类型消息,2条3类型消息,等会接收消息做实验。
![](https://images2015.cnblogs.com/blog/629717/201601/629717-20160115201524100-2139028659.png)
现在我们有6条消息了。
3.接收消息,编译msg_recv.c。我们主要来实验msgrcv()里面的msg_type参数。即该文件的第36行代码。
3.1:当msg_type等于0时,获取队列中第一个可用消息。
![](https://images2015.cnblogs.com/blog/629717/201601/629717-20160115202334741-1118689254.png)
可以看到,1234就是我刚刚第一次发送到该队列的消息。
3.2:当msg_type大于0,获取具有相同类型的第一个消息:
![](https://images2015.cnblogs.com/blog/629717/201601/629717-20160115202700147-99221565.png)
上面我们获取的是3类型的消息,接收的刚好是第一次发送3号消息的haha。
3.3:当msg_type小于0,获取等于或小于msg_type绝对值的第一个消息:
![](https://images2015.cnblogs.com/blog/629717/201601/629717-20160115203032241-1313977626.png)
上面,-3的绝对值是3,而队列中存在最先放进去的消息是1号消息22222(本来是1号的1234,刚刚我们做实验时读取走了,所以剩下它第一)。1小于3,所以1号消息被读取。
4.消息队列的删除,msg_recv.c里面第41行代码,如果放开后编译执行,收到一条消息后整个队列全部删除。
相关文章推荐
- Linux—进程间通讯—消息队列
- [转]Linux环境进程间通信 -- 消息队列
- linux消息队列的使用及内核实现原理
- Linux进程间通信&mdash;&mdash;消息队列
- Linux进程间通信——使用消息队列
- linux进程间通信之消息队列
- linux消息队列应用编程
- linux c++进程通信之消息队列
- linux下消息队列
- Linux进程通信之POSIX消息队列
- Linux 进程通信之 消息队列
- LINUX进程通信--消息队列
- 初学Linux--进程间通信(管道、消息队列)
- Linux IPC实践--System V消息队列(3)
- Linux编程之自定义消息队列
- Linux进程间通信——使用消息队列
- 学习linux消息队列通信
- linux下Posix消息队列的创建和删除
- linux进程间的通信(C): 消息队列
- linux 消息队列 和 内存共享的简短说明