【进程间通信方式二】消息队列

来源:互联网 发布:萨摩耶毛绒玩具淘宝 编辑:程序博客网 时间:2024/05/16 03:29

进程间通信(IPC)主要包括了管道、系统IPC(包括了消息队列、信号及共享存储)和套接字(SOCKET)。

IPC方法包括管道(PIPE)、消息队列(Message_Queue)、共用内存(ShareMemory)以及套接字(Socket)


消息队列

消息队列就是一个消息的链表。可以把消息看作一个记录,具有特定的格式以及特定的优先级。对消息队列有写权限的进程可以向消息队列中按照一定的规则添加新消息;对消息队列有读权限的进程则可以从消息队列中读走消息。每一个消息队列都有一个队列头,用结构struct msg_queue来描述。队列头包含了该消息队列的大量信息,包括消息队列键值、用户ID、组ID、消息队列中消息数目等等,设置记录了最近对消息队列读写进程的ID。读者可以访问这些信息,也可以设置其中的某些信息。


下面先来看一下系统中IPC对象数据结构内核为每个IPC对象维护的数据结构(/usr/include/linux/ipc.h)

在系统中消息队列,信号量和共享内存都有一个类似的数据结构。

相关参数说明:

key——用来标识唯一的消息队列资源

uid——拥有者ID

gid——拥有者组ID

cuid——创建者ID(这里需要强调一下,创建者有时并非是拥有者,例如:生产商生产出商品,属于商品的创建者,但是商品卖出后,商品的拥有者并不属于生产商)

cgid——创建者组ID(同上)

mode——为所采用的模式,可以将其理解为所具有的权限

系统中专门为消息队列提供的数据结构(/usr/include/linux/msg.h)


在进行进程间通信的时,主要使用的是下面几个结构体成员变量:

struct  ipc_perm  msg_perm——消息队列数据结构

struct  msg  *msg_first——消息队列头指针

struct  msg  *msg_last——消息队列尾指针


消息队列两个常用的操作指令

1)ipc -q——查看系统中所有的消息队列资源

2)ipcrm -q msgid——删除指定的msgid消息队列


模拟实现消息队列在两个进程之间的通信

1、创建消息队列(msgget)

#include <sys/types.h>#include <sys/ipc.h>#include <sys/msg.h>int msgget(key_t key, int msgflg);
参数说明:

(1)key值的设定方式(作用是标识唯一的一个消息队列)

A:直接设置为IPC_PRIVATE,其作用是相当于告诉OS要创建消息队列,此时的key值由操作系统自己指定,这种方法一般不使用

B:自定义产生key值,调用ftok()产生

#include <sys/types.h>#include <sys/ipc.h>key_t ftok(const char *pathname, int proj_id);
参数说明(这两个参数可以由用户根据需要自己指定):

pathname——指定路径

id——设定键值

(2)msgflg参数设定方式
A:IPC_CREAT——单独设置时一般都会成功,如果要创建的消息队列存在直接返回,如果不存在直接创建新的消息队列并返回
B:IPC_CREAT | IPC_EXCL——如果要创建的消息队列已经存在,则会出错返回,否则创建一个全新的消息队列并返回
C:IPC_EXCL——一般该参数不会单独使用,单独使用并没有什么意义
2、删除消息队列(msgctl)
#include <sys/types.h>#include <sys/ipc.h>#include <sys/msg.h>int msgctl(int msqid, int cmd, struct msqid_ds *buf);
参数说明:
msgid——指定消息队列的ID

cmd——在删除消息队列时,表示立即删除指定的消息队列

buf——用于对消息队列中的一些参数进行查找和修改(删除操作时可以直接将该参数忽略,直接设置为NULL)

函数返回值:成功返回0,失败返回-1

3、发送数据

#include <sys/types.h>#include <sys/ipc.h>#include <sys/msg.h>int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
参数说明:

msgbuf结构体

struct msgbuf {               long mtype;       /* message type, must be > 0 */               char mtext[1];    /* message data */           };

msgid——用来标识指定的消息队列

msgp——msgbuf结构体指针,发送缓冲区

msgsz——只是msgbuf中的mtext的大小

msgflg——设置发送方式,0表示非阻塞

4、接收数据

#include <sys/types.h>#include <sys/ipc.h>#include <sys/msg.h>ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);
参数说明: 

msgid——用来标识指定的消息队列

msgp——msgbuf结构体指针,接受缓冲区

msgsz——只是msgbuf中的mtext的大小

msgtyp——指示要接受消息的类型

msgflg——设置接收方式,0表示非阻塞


消息队列代码实现

1)comm.c(公共的头文件)


2)comm.c(公共头文件的具体实现)


3)client.c


4)server.c


5)Makefile文件

运行结果:



原创粉丝点击