【原创】《Linux高级程序设计》杨宗德著 - 进程管理与程序开发 - System V进程间通信之消息队列

时间:2021-02-05 10:24:09


【原创】《Linux高级程序设计》杨宗德著 - 进程管理与程序开发 - System V进程间通信之消息队列


消息队列IPC原理

【原创】《Linux高级程序设计》杨宗德著 - 进程管理与程序开发 - System V进程间通信之消息队列

消息队列数据结构struct msqid_ds

【原创】《Linux高级程序设计》杨宗德著 - 进程管理与程序开发 - System V进程间通信之消息队列

消息队列数据结构struct msg_msg

【原创】《Linux高级程序设计》杨宗德著 - 进程管理与程序开发 - System V进程间通信之消息队列

Linux消息队列管理

1. 创建消息队列

【原创】《Linux高级程序设计》杨宗德著 - 进程管理与程序开发 - System V进程间通信之消息队列

2. 消息队列属性控制

【原创】《Linux高级程序设计》杨宗德著 - 进程管理与程序开发 - System V进程间通信之消息队列

3. 发送消息到消息队列

【原创】《Linux高级程序设计》杨宗德著 - 进程管理与程序开发 - System V进程间通信之消息队列

【原创】《Linux高级程序设计》杨宗德著 - 进程管理与程序开发 - System V进程间通信之消息队列

4. 从消息队列接收消息

【原创】《Linux高级程序设计》杨宗德著 - 进程管理与程序开发 - System V进程间通信之消息队列

【原创】《Linux高级程序设计》杨宗德著 - 进程管理与程序开发 - System V进程间通信之消息队列

消息队列应用示例

1. 示例代码 - 读取消息队列基本信息

#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/ipc.h>
#include<string.h>
#include<sys/msg.h>
#define BUFSIZE 128
struct msg_buf
{
	long type;
	char msg[BUFSIZE];
};

int main(int argc,char *argv[])
{
	key_t key;
	int msgid;
	struct msg_buf msg_snd,msg_rcv;
	struct msginfo buf;
	char *ptr="helloworld";

	memset(&msg_snd,'\0',sizeof(struct msg_buf));
	memset(&msg_rcv,'\0',sizeof(struct msg_buf));
	msg_rcv.type=1;
	msg_snd.type=1;

	memcpy(msg_snd.msg,ptr,strlen(ptr));
	if((key=ftok(".",'A'))==-1)
	{
		perror("ftok");
		exit(EXIT_FAILURE);
	}

	if((msgid=msgget(key,0600|IPC_CREAT))==-1)
	{
		perror("msgget");
		exit(EXIT_FAILURE);
	}

	printf("msgsnd_return=%d\n",msgsnd(msgid,(void *)&msg_snd,strlen(msg_snd.msg),0));
	
	msgctl(msgid,MSG_INFO,&buf);
	printf("buf.msgmax=%d\n",buf.msgmax);
	printf("buf.msgmnb=%d\n",buf.msgmnb);
	printf("buf.msgpool=%d\n",buf.msgpool);
	printf("buf.semmap=%d\n",buf.msgmap);
	printf("buf.msgmni=%d\n",buf.msgmni);
	printf("buf.msgssz=%d\n",buf.msgssz);
	printf("buf.msgtql=%d\n",buf.msgtql);
	printf("buf.msgseg=%u\n",buf.msgseg);

	printf("msgrcv_return=%d\n",msgrcv(msgid,(void *)&msg_rcv,BUFSIZE,msg_rcv.type,0));
	printf("rev msg:%s\n",msg_rcv.msg);
	printf("msgctl_return=%d\n",msgctl(msgid,IPC_RMID,0));
}
运行结果:

$ ./msg_ipc_info 
msgsnd_return=0
buf.msgmax=8192
buf.msgmnb=16384
buf.msgpool=2
buf.semmap=1
buf.msgmni=1736
buf.msgssz=16
buf.msgtql=10
buf.msgseg=16384
msgrcv_return=10
rev msg:helloworld
msgctl_return=0

2. 使用消息队列实现实时通信

发送端:

#include<stdio.h>
#include<stdlib.h>
#include<sys/ipc.h>
#include<sys/msg.h>
#include<string.h>
struct msgbuf{
	int type;char ptr[0];
};
int main(int argc,char *argv[]){
	key_t key;key=ftok(argv[1],100);
	int msgid;msgid=msgget(key,IPC_CREAT|0600);
	pid_t pid;pid=fork();
	if(pid==0){
		while(1){
			printf("pls input msg to send:");char buf[128];fgets(buf,128,stdin);
			struct msgbuf *ptr=malloc(sizeof(struct msgbuf)+strlen(buf)+1);
			ptr->type=1;memcpy(ptr->ptr,buf,strlen(buf)+1);
			msgsnd(msgid,ptr,strlen(buf)+1,0);free(ptr);
		}
	}
	else{
		struct msgbuf{
			int type;char ptr[1024];
		};
		while(1){
			struct msgbuf mybuf;memset(&mybuf,'\0',sizeof(mybuf));
			msgrcv(msgid,&mybuf,1024,2,0);	printf("recv msg:%s\n",mybuf.ptr);
		}
	}
}
接收端:

#include<stdio.h>
#include<stdlib.h>
#include<sys/ipc.h>
#include<sys/msg.h>
#include<string.h>
struct msgbuf{
	int type;
	char ptr[0];
};
int main(int argc,char *argv[])
{
	key_t key;
	key=ftok(argv[1],100);

	int msgid;
	msgid=msgget(key,IPC_CREAT|0600);

	pid_t pid;
	pid=fork();
	if(pid==0)	//send
	{
		while(1)
		{
			printf("pls input msg to send:");
			char buf[128];
			fgets(buf,128,stdin);
			struct msgbuf *ptr=malloc(sizeof(struct msgbuf)+strlen(buf)+1);
			ptr->type=2;	//send msg type=2
			memcpy(ptr->ptr,buf,strlen(buf)+1);
			msgsnd(msgid,ptr,strlen(buf)+1,0);
			free(ptr);
		}
	}
	else
	{
		struct msgbuf{
			int type;
			char ptr[1024];
		};
		while(1)
		{
			struct msgbuf mybuf;
			memset(&mybuf,'\0',sizeof(mybuf));
			msgrcv(msgid,&mybuf,1024,1,0);	//recv msg type=2
			printf("recv msg:%s\n",mybuf.ptr);
		}
	}
}
发送端 - 终端1,运行结果:

$ ./msg_sender_example 
pls input msg to send:123
pls input msg to send:456
pls input msg to send:789
pls input msg to send:1234
pls input msg to send:
接收端 - 终端2 - 运行结果:

$ ./msg_receiver_example 
recv msg:123
recv msg:456
recv msg:789
recv msg:1234

发送端 - 终端1,运行结果:

pls input msg to send:abc
pls input msg to send:def
pls input msg to send:ghi
pls input msg to send:klm
接收端 - 终端2 - 运行结果:

recv msg:abc
recv msg:def
recv msg:ghi
recv msg:klm

需要强调的是,发送端和接收端的消息队列标识符要一致,以确保消息访问的队列一致,如果发送端和接收端消息队列不一致,则无法实现通信。

原文链接:

http://blog.csdn.net/geng823/article/details/41010115