Linux进程通信之消息队列
来源:互联网 发布:小米4能用移动4g网络吗 编辑:程序博客网 时间:2024/05/19 17:47
Linux进程通信之消息队列
消息队列就是一个消息的链表,我们可以把消息看作一个记录,具有特定的格式。消息队列也是进程中通信常见的方式之一,进程可以向消息队列中按照一定的规则添加新消息;另一些进程则可以从消息队列中读走消息。下面我们就来看看常见的消息队列函数:
(1) 创建或打开一个消息队列
int msgget(key_t key , intflag);
消息队列的通信编程与我前面学的信号量、共享内存差不多,都属于IPC结构,我们创建一个消息队列其实也就是创建一个消息队列的标识符。msgget的两个参数应该是非常清楚的,因为在我们的共享内存和信号量都会用到这两个参数,第一个就是我们的键值,用于产生我们的标识符,第二个参数是一个标志,指定消息队列的属性和权限。
该函数成功执行后就返回消息队列ID,以后我们就可以根据这个ID来访问这个消息队列。
(2) 将数据放到消息队列中
int msgsnd(int mspid , const void *ptr, size_t nbytes , int flag);
这个函数的参数有点多,我们来一一介绍一下
mspid:这个参数就是我们前面用msgget函数返回的消息队列的ID。
prt: prt参数指向一个准备发送消息的结构,这个结构如下:
struct mymesg{ long mtype;char mtext[512];}
该结构必须包含一个长整型成员变量,用来标志这个消息的类型。第二个成员就用来指定存放我们消息。
nbytes: 消息长度(不包括长整型成员变量的长度)。
flag:一般指定为IPC_NOWAIT,表示非阻塞状态。
该函数成功执行时返回0,否则返回-1。
(3)从消息队列中获取消息
ssize_t msgrcv(int msqid , void *ptr , size_t nbytes , long type , int flag);
该函数的参数更多,不过大部分与msgget函数的参数类似。
msqid :消息队里的ID。
prt:与msgget一样。
nbytes:获取消息的长度。
type: 获取消息的类型,上面我们说过prt指向的结构体,有一个参数是指定消息的类型,我们在获取消息时,就要指定这个类型。如果type为0,就获取队列中的第一个消息。如果它的值大于0,将获取指定类型的消息,如果小于0,就获取类型等于或者小于type的绝对值的第一个消息。
flag:一般指定为IPC_NOWAIT。
该函数执行成功后返回消息的数据部分的长度,以字节为单位,否则返回-1。
需要说明的是,从msqid代表的消息队列中读取一个type类型的消息,并把消息存储在msgbuf结构中,在成功地读取了一条消息以后,队列中的这条消息将被删除。
(4)控制消息队列
int msgctl(int msgid , int command , struct msgid_ds *buf);
该函数用来控制消息队列,它与共享内存的shmctl函数类似,其参数意义为:
msgid: 为获取消息队列的标识符。
command:该参数说明对由msgid指定的队列要执行的命令:
IPC_STAT:取此队列的msqid_ds结构,并将它存放在buf指向的结构中。
IPC_SET:按由buf指向结构中的值,设置该队列的msqid_ds结构,不过该命令需要有足够的权限才能执行。
IPC_RMID:删除消息队列。
buf:是指向msgid_ds结构的指针,我们知道,在创建一个消息队列的时候,内核为每一消息队列都会指定一个关联结构,该结构包含了该消息队列的相关信息,msgid_ds就是这样的一个结构。
该函数成功时返回0,否则返回-1.
说太多理论的东西可能不太好理解,下面我们就来写一个实例程序,利用消息队列方式实现两个不相关进程间的通信:
发送进程程序:
#include <stdio.h>#include <sys/types.h>#include <sys/ipc.h>#include <sys/msg.h>#include <unistd.h>#include <string.h> #define MAX 256struct msgbuf { long int mtype; char mtext[MAX]; };void main(){ int mspid; key_t key; int ret; struct msgbuf mymsg; //创建一个消息队列,首先获取键值 key = ftok("/home" , 1); mspid = msgget(key ,IPC_CREAT|0666); if(mspid==-1) { printf("creat the queuefailure\n"); return; } //向消息队列中填入数据,需要定义一个结构体 mymsg.mtype = 1; strncpy(mymsg.mtext , "it is a memsg_queue test!" , 30); ret = msgsnd(mspid , &mymsg , 256 ,IPC_NOWAIT); if(ret == -1) { printf("send memsage failure\n"); return; } }
接收进程程序:
#include <stdio.h>#include <sys/types.h>#include <sys/ipc.h>#include <sys/msg.h>#include <unistd.h>#include <string.h> struct msgbuf { long mtype; char mtext[256]; };void main(){ int msqid; key_t key; int size; struct msgbuf mymsg; //获取一个消息队列,首先获取键值 key = ftok("/home" , 1); msqid = msgget(key ,IPC_CREAT|0666); if(msqid==-1) { printf("creat the queuefailure\n"); return; } //读取一个消息队列中的内容 msgrcv(msqid , &mymsg ,sizeof(mymsg.mtext),1 , IPC_NOWAIT); printf("the msg is : %s\n",mymsg.mtext); //删除消息队列 if( msgctl(msqid , IPC_RMID , 0) == -1) { printf("delete the queuefailure\n"); return; } }
发送进程程序创建一个消息队列,并向其中写入“it is a memsg_queue test!“这条消息语句,接收进程就获取这个消息队列,然后取出其中的消息,并打印出来,程序中关键的地方都有解释,需要注意的就是消息队列结构体的长整型,发送进程和接收进程此值一定要对应,否则读不出要的消息。打开linux命令行,在命令行中编译运行这两个程序,先运行发送进程,然后运行接收进程,可以发现我们的接收进程正确的获取了我们消息队列中的消息。有个细节大家注意没,我们运行发送进程后,在运行接收进程可以接收到消息,然后再运行我们的接收进程却收不到消息,这是为什么?我们前面在学习共享内存的时候,写入进程写入数据后,我们读取进程可以多次读取到数据,可是在消息队列中却只能读一次,原因是前面我们提到了在成功地读取了消息队列中的一条消息以后,队列中的这条消息将被删除。因此要想多次读取同样的消息,就得让发送进程多次发送。
以上便是linux进程通信之消息队列的简单介绍,希望得到指正。
- linux进程间通信之消息队列
- linux进程间通信之消息队列
- linux进程间通信之消息队列
- Linux进程间通信之消息队列
- Linux进程通信之消息队列
- linux 进程间通信之消息队列
- linux进程间通信之消息队列
- linux进程间通信之消息队列
- Linux下进程通信之消息队列
- Linux进程通信之POSIX消息队列
- Linux进程通信之POSIX消息队列
- linux进程通信之消息队列
- Linux进程通信之POSIX消息队列
- linux进程间通信之消息队列
- linux进程间通信之消息队列
- linux c++进程通信之消息队列
- Linux进程通信之POSIX消息队列
- linux进程间通信之消息队列
- JSP运行原理以及执行过程源码分析
- 程序员的想法
- GRE填空答案如何准确推断?
- TCP/IP 网络栈 & 编写网络应用
- Duilib中Scrollbar的设置问题
- Linux进程通信之消息队列
- Java Web框架之一层模型-JSP实现
- Linux下网络流量实时监控工具 大全
- 最小二乘支持向量机(LSSVM)简述
- NSString什么时候用copy,什么时候用strong
- Jmeter http请求 Demo(压测Elasticsearch)
- 黑马程序员——java基础之IO流
- 修改 openstack 中 nova boot 创建实例只能在10个以内的限制
- 指针函数与函数指针的区别