- 消息队列是进程之间进行通信的另一种方式。其中无名管道用于两个进程间进行通信;有名管道可用于多个进程间进行通信;消息队列同样用于多进程之间的通信。
- 特点
- 消息队列中的消息是有类型和格式的,可以实现随机查询,不一定妖遵循先入先出的顺序,可以按照消息类型读取
- 读出数据后,数据会被删除
- 消息队列允许一个或多个进程对其进行写入及读取数据
- 内核重启或人为删除才会删除消息队列,否则会一直存在于系统中
- 唯一Key值
- 系统中可能会同时存在很多消息队列,怎么区分操作的是哪一个呢?通过Key值进行指定。
- 共享内存、信号、消息队列都需要使用Key值(通过ftok()函数创建)
- ftok函数
#include <sys/types.h> #include <sys/ipc.h> key_t ftok(const char * filename, int proj_id); 功能:获取唯一的Key值 参数: filename:路径名(可以随便设置) proj_id:项目ID(1-255(非零整数)) 返回值: 成功返回Key值,失败返回-1
- 创建消息队列--msgget函数
#include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h> int msgget(key_t key, int msgflag); 功能: 创建或打开消息队列 注意: 以下两种情况,将创建一个新的消息队列 1、若没有与Key值相同的消息队列,且msgflg标志位包含IPC_CREATE 2、key参数为IPC_PRIVATE 参数: key:消息队列的id值(ftok函数的返回值) msgflag:权限标志位,可以与IPC_CRAETE做或操作(IPC_CREATE|0777),当key命名的消息队列不存在 时,创建一个新的消息队列,若存在,则忽略IPC_CREATE,返回标识符 返回值: 成功返回id值,失败返回-1
-
发送消息--msgsnd函
#include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h> int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg); 作用:将消息发送到消息队列中 参数: msqid:消息队列id msgp:待发送消息的缓冲区地址 msgsz:待发送消息的字节数 msgflag:IPC_NOWAIT(如果消息队列中的空间不足,则msgsnd的默认行为是阻塞,直到空间变为可用。如 果msgflg设置为IPC_NOWAIT,则调用会失败,并返回错误EAGAIN) NULL表示阻塞,直到空间可用 返回值: 成功返回0,失败返回-1
-
接收消息--msgrcv函数
#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); 功能: 接受消息队列的消息 参数: msqid:消息队列的id msgp:存放接收消息的缓冲区 msgsz:要接收消息的字节数 msgtyp: type = 0:返回队列中的第一个消息 type > 0: 返回队列中消息类型为type的第一个消息 type < 0,返回队列中消息类型值小于或等于type绝对值的消息,如果有多个,则取类型值最小的消息 msgflg: 0:若消息队列中无消息则一直处于阻塞状态 IPC_NOWAIT:若没有消息,进程会立即返回ENOMSG 返回值: 成功返回接收到的消息长度 失败返回-1
-
msgctl函数
#include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h> int msgctl(int msqid, int cmd, struct msqid_ds *buf); 功能:主要用于删除消息队列 参数: msqid:消息队列的队列ID cmd: IPC_RMID:删除消息队列 buf:NULL 返回值: 成功返回0,失败返回-1
-
msgsnd.c文件
//msgrcv.c文件 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/types.h> #include <sys/msg.h> #include <sys/ipc.h> typedef struct msgBuf{ long myType; char mText[1024]; }MSGBUF; int main(void){ int msgId, msgSnd, msgRcv, msgCtl; MSGBUF rcvBuf; MSGBUF sndBuf = {222, "Hello, I'm msgrcv process!\n"}; //1、生成key值 key_t key = ftok(".", 1); if(key < 0){ printf("ftok failed!\n"); exit(-1); } //2、创建消息队列 msgId = msgget(key, IPC_CREAT|0777); if(msgId < 0){ printf("msgget failed!\n"); exit(-1); } //3、接收消息 msgRcv = msgrcv(msgId, &rcvBuf, sizeof(rcvBuf.mText), 111, 0); if(msgRcv < 0){ printf("msgrcv failed!\n"); exit(-1); } printf("接收到的消息为: %s\n", rcvBuf.mText); //4、发送消息 msgSnd = msgsnd(msgId, &sndBuf, sizeof(sndBuf.mText), 0); if(msgSnd < 0){ printf("msgsnd failed!\n"); exit(-1); } //删除消息队列 msgctl(msgId, IPC_RMID, NULL); if(msgCtl < 0 ){ printf("msgctl failed!\n"); exit(-1); } return 0; }
//msgsnd.c文件 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/types.h> #include <sys/msg.h> #include <sys/ipc.h> typedef struct msgBuf{ long myType; char mText[1024]; }MSGBUF; int main(void){ int msgId, msgSnd, msgRcv, msgCtl; MSGBUF rcvBuf; MSGBUF sndBuf = {111, "Hello, I'm msgsnd process!\n"}; //1、生成key值 key_t key = ftok(".", 1); if(key < 0){ printf("ftok failed!\n"); exit(-1); } //2、创建消息队列 msgId = msgget(key, IPC_CREAT|0777); if(msgId < 0){ printf("msgget failed!\n"); exit(-1); } //3、发送消息 msgSnd = msgsnd(msgId, &sndBuf, sizeof(sndBuf.mText), 0); if(msgSnd < 0){ printf("msgsnd failed!\n"); exit(-1); } //接收消息 msgRcv = msgrcv(msgId, &rcvBuf, sizeof(rcvBuf.mText), 222, 0); if(msgRcv < 0){ printf("msgrcv failed!\n"); exit(-1); } printf("接收到的消息为: %s\n", rcvBuf.mText); //删除消息队列 msgctl(msgId, IPC_RMID, NULL); if(msgCtl < 0 ){ printf("msgctl failed!\n"); exit(-1); } return 0; }
-
运行结果
今天就记录到这里。