进程的IPC操作 之 消息队列

目录

一 消息队列

二 消息队列的相关函数

2.1 消息队列的创建

2.2 消息的发送

2.3 消息的接收

2.4 消息的设置

三 测试案例


一 消息队列

消息队列是一种进程间的通讯的消息队列,能够独立于读端和写段,如果发送或者接收进程终止了,其中的消息也不会消失,并且进程可以按照类型对消息队列进行读写。

二 消息队列的相关函数

消息队列的函数定义在sys/msg.h头文件中。

2.1 消息队列的创建

int msgget(key_t key, int msgflg);

函数功能:主要是在内核创建一个消息队列。

函数参数:

1.key:主要是用于全局表示这个IPC资源:消息队列的唯一性;

2.msgflg:和信号量semget()函数的sem_flags参数的取值相同。

当该函数创建成功时,会在内核建立一个该消息队列的msgid_ds结构体变量:

struct msqid_ds
{
    struct ipc_perm msg_perm;/*消息队列的操作权限*/
    time_t msg_stime;/*最后一次调用msgsnd的时间*/
    time_t msg_rtime;/*最后一次调用msgrcv的时间*/
    time_t msg_ctime;/*最后一次被修改的时间*/
    unsigned long__msg_cbytes;/*消息队列中已有的字节数*/
    msgqnum_t msg_qnum;/*消息队列中已有的消息数*/
    msglen_t msg_qbytes;/*消息队列允许的最大字节数*/
    pid_t msg_lspid;/*最后执行msgsnd的进程的PID*/
    pid_t msg_lrpid;/*最后执行msgrcv的进程的PID*/
};

2.2 消息的发送

int msgsnd(int msgid, const void* msg_ptr, size_t msg_sz, int msgflg);

函数功能:主要用于向msgid标识的消息队列发送size大小的由msg_ptr所指向的消息。

函数参数:

1.msgid:由msgget()函数返回的消息队列标识符;

2.msg_ptr:发送的消息,具体结构如下所示:

struct msgbuf{
    long mtype;
    char mtext[512];
};

3.msg_sz:发送的消息msgbuf中mtext字符数组的实际数据长度;

4.msgflg:主要就是IPC_NOWAIT参数,当消息队列满的时候,会阻塞,直到:a.消息队列不满;b.消息队列被进程移除,会返回EIDRM错误;c.该函数被中断后,会返回EINTR错误。如果不设置IPC_NOWAIT参数,则不会阻塞,如果消息队列已满设置errno为EAGAIN。

2.3 消息的接收

int msgrcv(int msgid, void* msg_ptr, size_t msg_sz, long int msg_type, int msgflg);

函数功能:主要用于接收由msgid标识的消息队列中,大小为msg_sz字节,消息类型为msg_type类型的消息,存储在msg_ptr指针指向的结构体msgbuf中。

函数参数:

1.msg_type的取值:

a.当msg_type大于0时,用于获取消息类型mtype为msg_type的消息;

b.当msg_type等于0时,用于获取消息队列第一个消息;

c.当msg_type小于0时,用于获取消息队列中第一个小于msg_type的绝对值的消息。

2.msgflg:主要有如下取值:

a.IPC_NOWAIT:如果消息队列中没有消息,则不阻塞直接返回,并且设置errno为ENOMSG;

b.MSG_EXCEPT:用于获取消息队列第一个非msg_type类型的消息;

c.MSG_NOERROR:当消息的长度大于msg_size,则将多余的部分截断。

2.4 消息的设置

int msgctl(int msgid, int command, msgid_ds* buf);

函数功能:用于对消息队列的属性进行设置。

函数参数:

1.IPC_STAT:用于将消息队列的msgid_ds结构体存储在buf指针指向的地址中;

2.IPC_SET:与IPC_STAT的功能相反;

3.IPC_RMID:将消息队列从内核中移除,唤醒所有等待读写该消息队列的进程。

三 测试案例

一个进程往消息队列里面写入数据,一个进程从消息队列中读出数据:

读进程:

#include<stdio.h>
#include<sys/msg.h>
#include<stdlib.h>
#include<string.h>

#define MSG_KEY 0x1234
#define MSG_SIZE 512
#define MSG_TYPE 123

struct msgbuf{
	long mtype;
	char mtext[MSG_SIZE];
};

int main()
{
	int msg_id = msgget(MSG_KEY, IPC_CREAT|0666);
	if(msg_id == -1)
	{
		printf("创建消息队列失败\n");
		return -1;
	}
	struct msgbuf read_buf;
	int nread = msgrcv(msg_id, &read_buf, sizeof(read_buf.mtext), MSG_TYPE, 0);
	if(nread == -1)
		printf("读消息队列失败\n");
	else
		printf("读消息队列成功:%s\n", read_buf.mtext);
	struct msqid_ds buf;
	msgctl(msg_id, IPC_RMID, &buf);
	return 0;
}

写进程:

#include<stdio.h>
#include<sys/msg.h>
#include<stdlib.h>
#include<string.h>

#define MSG_KEY 0x1234
#define MSG_SIZE 512
#define MSG_TYPE 123

struct msgbuf{
	long mtype;
	char mtext[MSG_SIZE];
};

int main()
{
	int msg_id = msgget(MSG_KEY, IPC_CREAT|0666);
	if(msg_id == -1)
	{
		printf("创建消息队列失败\n");
		return -1;
	}
	struct msgbuf send_buf = {MSG_TYPE, "这是写进程"};
	int nsend = msgsnd(msg_id, &send_buf, sizeof(send_buf.mtext), 0);
	if(nsend == -1) printf("读消息队列失败\n");
	else printf("写消息队列成功\n");
	return 0;
}

测试结果:

 

 

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值