Linux进程间通信第四讲 标准IPC之消息队列
目录4.2消息队列4.2.1 概念和原理4.2.2 使用4.2消息队列4.2.1 概念和原理消息队列是另一种标准IPC,当然也大概遵循大部分标准消息队列,它是存放消息(数据)的队列,而队列是先进先出的线性数据结构换句话说,我们就是利用这个数据结构 进行进程间的通信消息队列允许多个进程同时读写消息.由于消息可以定义很多类型,取出时可以指定哪个消息类型取出,所以...
目录
4.2 消息队列
4.2.1 概念和原理
消息队列是另一种标准IPC,当然也大概遵循大部分标准
消息队列,它是存放消息(数据)的队列,而队列是先进先出的线性数据结构
换句话说,我们就是利用这个数据结构 进行进程间的通信
消息队列允许多个进程同时读写消息.由于消息可以定义很多类型,取出时可以指定哪个消息类型取出,所以消息队列解决了共享内存多个进程同时读写时数据混乱的问题,只要把消息标定不同的类型即可
4.2.2 使用
1)通过ftok获取key
2)通过key 创建/获取 消息队列 ------- msgget
参数:
key - 上一步获取的key
msgflg - 创建标志和权限
IPC_CREAT|0666
成功返回消息队列ID,失败返回-1
3)把消息 存入队列 / 从队列中取出 ----------- msgsnd/msgrcv
参数:
msqid - 消息队列ID
msgq - 消息首地址
msgsz - 消息长度(消息数据的长度)
msgtyp - 用来指定接收什么类型的消息(仅仅接收消息时才有)
0:接收任意类型消息(第一个,先进先出)
>0:接收类型为msgtyp的特定消息
<0:接收类型 小于等于 msgtyp绝对值的小,类型从小到大接收
msgflg - 接收/发送 标识
0表示阻塞方式操作,接收消息没有消息可接收/发送消息消息队列满了 就会等待直到成功
IPC_NOWAIT表示非阻塞方式操作,接收消息没有消息可接收/发送消息消息队列满了 直接返回错误
msgsnd成功返回0,msgrcv成功返回收到消息的消息数据长度,失败都返回-1
另外,消息类型在系统中是未定义的,所以程序员需要在代码中自己定义消息的类型,但是必须按照以下形式:
struct msgbuf {
long mtype; /* 消息类型, 必须大于0 */
char mtext[1]; /* 消息数据, 即存放的数据 */
};
4)不再使用可以删除消息队列 ------- msgctl
参数:
msqid - 消息队列ID
cmd - 命令
IPC_RMID:删除
IPC_SET: 修改
IPC_STAT: 获取
buf - 设置/获取 时 传入/传出 消息队列的信息, 下面是它的数据类型 ,其中可以修改的是uid、gid和mode
msgctl函数成功返回0,失败返回-1
struct msqid_ds {
struct ipc_perm msg_perm; /* Ownership and permissions */
time_t msg_stime; /* 最后发送消息时间 */
time_t msg_rtime; /* 最后接收消息时间 */
time_t msg_ctime; /* 最后修改时间 */
unsigned long __msg_cbytes; /* 当前使用消息队列空间大小 (nonstandard) */
msgqnum_t msg_qnum; /* 当前消息个数 */
msglen_t msg_qbytes; /* 消息队列最大长度 */
pid_t msg_lspid; /* 最后发送消息的PID */
pid_t msg_lrpid; /* 最后接收消息的PID */
};
struct ipc_perm {
key_t __key; /* Key supplied to msgget(2) */
uid_t uid; /* Effective UID of owner */
gid_t gid; /* Effective GID of owner */
uid_t cuid; /* Effective UID of creator */
gid_t cgid; /* Effective GID of creator */
unsigned short mode; /* Permissions */
unsigned short __seq; /* Sequence number */
};
消息队列发送端代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/ipc.h>
#include <sys/msg.h>
struct MSG{
long mtype;
char mtext[100];
};
int main()
{
//1.获取key
key_t key = ftok(".",'x');
if(key==-1){
perror("ftok");
exit(-1);
}
//2.创建消息队列
int msqid = msgget(key,IPC_CREAT|0666);
if(msqid==-1){
perror("shmget");
exit(-1);
}
//3.发送消息
struct MSG msg1;
msg1.mtype = 1;//类型1
strcpy(msg1.mtext,"liubei");
int res = msgsnd(msqid,&msg1,sizeof(msg1.mtext),0);
if(res==-1){
perror("msgsnd");
exit(-1);
}
msg1.mtype = 2;//类型2
strcpy(msg1.mtext,"guanyu");
res = msgsnd(msqid,&msg1,sizeof(msg1.mtext),0);
if(res==-1){
perror("msgsnd");
exit(-1);
}
printf("消息发送成功!\n");
return 0;
}
消息队列接收端代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <errno.h>
extern int errno;
struct MSG{
long mtype;
char mtext[100];
};
int main()
{
//1.获取key
key_t key = ftok(".",'x');
if(key==-1){
perror("ftok");
exit(-1);
}
//2.获取消息队列
int msqid = msgget(key,0);
if(msqid==-1){
perror("shmget");
exit(-1);
}
//3.接收消息
struct MSG msg1;
while(1){
//类型-2,方式非阻塞
int res = msgrcv(msqid,&msg1,sizeof(msg1.mtext),/*-2*/0,IPC_NOWAIT);
//接收完成删除消息队列
if(res==-1&&errno==ENOMSG){
break;
}
else if(res==-1&&errno!=ENOMSG){
perror("msgrcv");
exit(-1);
}
else{
printf("消息类型 = %ld,消息内容 = %s\n",msg1.mtype,msg1.mtext);
}
}
msgctl(msqid,IPC_RMID,0);
printf("消息队列删除成功!\n");
return 0;
}
输出如下:
liaowenbindeMacBook-Pro:3 liaowenbin$ ./4msg
消息发送成功!
liaowenbindeMacBook-Pro:3 liaowenbin$ gcc 5msg.c -o 5msg
liaowenbindeMacBook-Pro:3 liaowenbin$ ./5msg
消息类型 = 1,消息内容 = liubei
消息类型 = 2,消息内容 = guanyu
消息队列删除成功!
更多推荐
所有评论(0)