消息队列是SystemV版本中三种进程通信机制之一,另外两种是信号量和共享存储段。消息队列提供了进程间发送数据块的方法,而且每个数据块都有一个类型标识。消息队列是基于消息的,而管道是基于字节流。创建的消息队列,生命周期随内核,只有内核重启或用户主动去删除,才可以真正关闭消息队列。
一个或多个进程可向消息队列写入消息,而一个或多个进程可从消息队列中读取消息,这种进程间通讯机制通常使用在客户/服务器模型中,客户向服务器发送请求消息,服务器读取消息并执行相应请求。在许多微内核结构的操作系统中,内核和各组件之间的基本通讯方式就是消息队列。例如,在 MINIX 操作系统中,内核、I/O 任务、服务器进程和用户进程之间就是通过消息队列实现通讯的。
Python:
Python 的 multiprocessing 模块中提供了同步的、线程安全的队列类,FIFO(先入先出)队列Queue。
python queue模块有三种队列:
1、python queue模块的FIFO队列先进先出。
2、LIFO类似于堆。即先进后出。
3、还有一种是优先级队列级别越低越先出来。
针对这三种队列分别有三个构造函数:
1、class Queue.Queue(maxsize) FIFO
2、class Queue.LifoQueue(maxsize) LIFO
3、class Queue.PriorityQueue(maxsize) 优先级队列
Queue 模块中的常用方法:
Queue.qsize() 返回队列的大小
Queue.empty() 如果队列为空,返回True,反之False
Queue.full() 如果队列满了,返回True,反之False
Queue.full 与 maxsize 大小对应
Queue.get([block[, timeout]])获取队列,timeout等待时间
Queue.get_nowait() 相当Queue.get(False)
Queue.put(item) 写入队列,timeout等待时间
Queue.put_nowait(item) 相当Queue.put(item, False)
Queue.task_done() 在完成一项工作之后,Queue.task_done()函数向任务已经完成的队列发送一个信号
Queue.join() 实际上意味着等到队列为空,再执行别的操作
#!/usr/bin/python3
import multiprocessing
def put_queue(queue):
for i in range(5):
queue.put(i)
def get_queue(queue):
while not queue.empty():
print(queue.get())
queue = multiprocessing.Queue()
put_p = multiprocessing.Process(target=put_queue,args=(queue,))
get_p = multiprocessing.Process(target=get_queue,args=(queue,))
put_p.start()
put_p.join()
get_p.start()
C:
int msgget(key_t key, int msgflg);
获取消息队列还是获取共享内存,就像打开文件一样,这个文件可能存在也可能不存在。
获取一个消息队列之后会返回一个消息队列的句柄
操作消息队列
int msgctl(int msqid, int cmd, struct msqid_ds *buf);
消息队列的发送
int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
获取消息队列
ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);
#include <signal.h>
#include "head4msg.h"
int main(int argc, char **argv)
{
key_t key = ftok(PROJ_PATH, PROJ_ID);
int msgid = msgget(key, IPC_CREAT | 0666);
struct msgbuf buf;
bzero(&buf, sizeof(buf));
if(msgrcv(msgid, &buf, MSGSIZE, J2R, 0) == -1)
{
perror("msgrcv() error");
exit(1);
}
printf("from msg: %s", buf.mtext);
msgctl(msgid, IPC_RMID, NULL);
return 0;
}
#include "head4msg.h"
int main(int argc, char **argv)
{
key_t key = ftok(PROJ_PATH, PROJ_ID);
int msgid = msgget(key, IPC_CREAT | 0666);
struct msgbuf message;
bzero(&message, sizeof(message));
message.mtype = J2R;
strncpy(message.mtext, "abcxyz\n", MSGSIZE);
if(msgsnd(msgid, &message, strlen(message.mtext), 0) != 0)
{
perror("msgsnd() error");
exit(1);
}
return 0;
}