weiqi7777

进击吧,linux(十八) 消息队列通讯

0
阅读(2278)

Linux进程和进程之间有多种通讯方式。Linux进程间通讯的主要方式有:

1、无名管道

2、有名管道

3、信号

4、消息队列

5、共享内存

6、信号量

7、套接字

消息队列就是一个消息的链表。而一条消息可以看作是一个记录,具有特定的格式。进程可以向消息队列中按照一定的规则添加新消息,另一个进程可以从消息队列中读取消息,这样通过消息对了,就实现了进程间的通讯。

clip_image002

同样,对于消息队列,也是有若干函数。

9.1创建或打开消息队列

9.1.1函数名

msgget

9.1.2函数原型

int msgget(key_t key, int msgflg)

9.1.3函数功能

打开或创建消息队列

9.1.4函数所属头文件

9.1.5函数返回值

成功:消息对应标识符id

失败:-1

9.1.6函数参数

key消息队列关联的键值

msgflg打开标志

-IPC_CREAT:如果打开消息队列失败,则创建新的消息队列

9.2写消息

9.2.1函数名

msgsnd

9.2.2函数原型

int msgsnd(int msqid, const void *msgp, size_t msgsz,int msgflg)

9.2.3函数功能

往消息队列里面发送消息

9.2.4函数所属头文件

9.2.5函数返回值

成功:0

失败:-1

9.2.6函数参数

msqid:消息队列的标识符id

msgp:指向要发送的消息指针

clip_image003

mtext的大小由msgzz决定

msgsz:消息数据的大小

msgflg:标志

9.3读消息

9.3.1函数名

msgrcv

9.3.2函数原型

ssize_t msgrcv(int msgid, void *msgp, size_t msgsz, long msgtyp, int msgflg)

9.3.3函数功能

从消息队列获取消息

9.3.4函数所属头文件

9.3.5函数返回值

成功:实际接收到的消息的数据量

失败:-1

9.3.6函数参数

msgid:消息队列的id

msgp消息指针

clip_image003

msgsz希望取到消息的数据长度

msgtyp:消息类型

-0消息队列的第一条消息取出

-大于0取消息队列中第一条类型等于msgtyp的消息

-小于0取消息队列中类型不超过msgtyp的绝对值中最小的消息

msgflg标志

9.4删除消息队列

9.4.1函数名

msgctl

9.4.2函数原型

int msgctl(int msgid, int cmd, struct msqid_ds *buf)

9.4.3函数功能

消息队列的操作

9.4.4函数所属头文件

9.4.5函数返回值

成功:0

失败:-1

9.4.6函数参数

msgid:消息队列id

cmd:命令

-IPC_STAT:将内核数据复制到buf

-IPC_SET:设置buf参数,并该buf数据复制到内核数据中

-IPC_RMID:删除消息队列

buf:结构体指针

clip_image005

下面,就是写代码进行学习了。

有两个进程AB,进程A创建消息队列,并向消息队列中写数据,进程B从消息队列中读取数据。

#include #include #include #include #include struct msgbuf{ long mtype; char mtext[1024]; }; void main() { key_t key; int msqid; char in[1024]; struct msgbuf msg; int msg_type; /*获取键值*/ key = ftok("/home",7); /*创建消息队列*/ msqid = msgget(key,IPC_CREAT); while(1) { printf("please input message type\n"); /*获取键盘输入*/ scanf("%d",&msg_type); printf("please input message content \n"); scanf("%s",in); msg.mtype = msg_type; strcpy(msg.mtext,in); /*发送到消息队列*/ msgsnd(msqid,&msg,sizeof(struct msgbuf),0); if(msg_type == 7777) break; } /*删除消息队列*/ msgctl(msqid,IPC_RMID,0); }

进程A中定义了一个结构体,这个结构体就是消息队列中规定的消息的结构体。第一个成员是消息类型,规定要大于0。第二个是消息内容数组,用来保存消息的数据。

首先是创建一个键值,然后创建消息队列和键值关联起来。然后就是一个无限循环,往消息队列中写入消息。如果一次消息发送的类型是7777,就退出循环,然后把消息队列删除。

进程B

#include #include #include #include #include struct msgbuf{ long mtype; char mtext[1024]; }; void main() { key_t key; int msqid; struct msgbuf msg; key = ftok("/home",7); /*打开消息队列*/ msqid = msgget(key, IPC_CREAT); while(1) { /*接收消息队列*/ msgrcv(msqid,&msg,sizeof(struct msgbuf),0,0); /*打印消息队列*/ printf("%d\n",msg.mtype); printf("%s\n",msg.mtext); if(msg.mtype == 7777) break; } }

进程B中也定义了一个和进程A中一样的结构体,功能是一样的。

先创建键值,并打开与键值关联的消息队列,这样就可以和A进程进行消息通信了。然后就不断读取消息队列中的数据,打印出来,如果消息队列中的数据的类型是7777,就退出循环。

这里接收消息用的是

msgrcv(msqid,&msg,sizeof(structmsgbuf),0,0);

第三个参数是0,表示接收消息队列的第一个数据。

程序运行:

B进程在等待读取消息数据,因为A进程还没有发送消息,所以就被阻塞了。

clip_image007

A进程发送消息后,B进程就会收到该消息,然后将该消息打印出来。

clip_image009

当发送消息的类型是7777AB进程就结束运行了。

clip_image011

B进程的接收消息队列改为

msgrcv(msqid,&msg,sizeof(structmsgbuf),7,0);

表示只从消息队列中读取类型为7的消息。

运行程序的话,发送的消息类型不是7,就一直等待接收消息。

clip_image013

当发送消息类型为7,就接收消息。

clip_image015

B进程的接收消息队列改为

msgrcv(msqid,&msg,sizeof(structmsgbuf),-7,0);

表示只从消息队列中读取类型为1——7的消息。

运行程序的话,发送消息类型为15,超过7,所以B进程等待接收消息。

clip_image017

当发送消息的类型不超过7后,B进程接收消息。

clip_image019

以上,就是消息队列通信了,消息队列通信,对于接收,有3种方式,一种是接收消息队列的第一个,一个是接收消息队列中指定的类型消息,最后一个是接收消息队列中的指定的范围类型的消息。

Baidu
map