Linux进程间通信之三:消息队列

README

1、首先有两个程序:p1.c、p2.c;

2、这两个程序先后运行之后系统会创建两个进程(下面统称为p1、p2);

3、p1首先申请一个消息队列,并创建两个信号量

4、p2打开消息队列、打开信号量

5、p1从键盘获取字符串,封装好一个消息,然后发送消息到队列

6、p2从队列读取消息,并打印出消息正文

7、通信过程中使用posix有名信号量实现同步(即p1写完队列p2才能读取队列)

通过ipcs -q 查看所创建的消息队列
————————————————
版权声明:本文为CSDN博主「独步逍遥&万界仙踪」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/gogo0707/article/details/124594711

p1.c

#include <stdio.h>
#include <sys/types.h>
#include <string.h>
#include <unistd.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <semaphore.h>

struct msgbuf{
	long msgtype; //massage type must be > 0 
	char mtext[100];
};

int main(void)
{
	int msgid; //save message queue id
	sem_t *sem1 = NULL; //save named semaphore addr1
	sem_t *sem2 = NULL; //...
	msgid = msgget((key_t)123,IPC_CREAT|0777);//creat a message queue
	if(msgid <0){
		perror("creat a msg queue fail");
		return -1;
	}
	sem_unlink("sem1");
	//创建或打开一个POSIX有名信号量
	sem1 = sem_open("sem1",O_CREAT|O_RDWR,0666,1);//value init=1
	if(sem1 == SEM_FAILED){
		perror("open sem1 fail");
		return -1;
	}
	//创建或打开一个POSIX有名信号量
	sem2 = sem_open("sem2",O_CREAT|O_RDWR,0666,0);//value init=0
	if(sem2 == SEM_FAILED){
		perror("open sem2 fail");
		return -1;
	}
	struct msgbuf msg_to_send;
	msg_to_send.msgtype = 1;
	while(1){
		//等待信号量有效、P操作
		sem_wait(sem1);
		printf("Please input text to send:");
		if(fgets(msg_to_send.mtext,100,stdin) != msg_to_send.mtext){
			perror("get char from stdin fail");
			return -2;
		}
		if(msgsnd(msgid,&msg_to_send,100,0)<0){
			perror("send msg to queue fail");
			return -3;
		}
		//释放信号量,V操作
		sem_post(sem2);
		if(strncmp("quit",msg_to_send.mtext,4)==0){
			printf("p1 readys to quit\n");
			break;
		}
	}

	struct msqid_ds msg_ds;
	struct msginfo msg_info;
	msgctl(msgid,IPC_STAT,&msg_ds);
	printf("==%lu,%lu,%lu==\n",msg_ds.__msg_cbytes,msg_ds.msg_qnum,msg_ds.msg_qbytes);

	int array_id = msgctl(msgid,MSG_INFO,(struct msqid_ds *)&msg_info);
	printf("==%d,%d,%d,%d==\n",msg_info.msgpool,msg_info.msgmap,msg_info.msgtql,array_id);

	sleep(2);
	//释放各种资源
	sem_close(sem1);
	sem_close(sem2);
	if(msgctl(msgid,IPC_RMID,NULL)<0){
		perror("remove msg queue fail");
	}
	return 0;
}
	

p2.c

#include <stdio.h>
#include <sys/types.h>
#include <string.h>
#include <fcntl.h>
#include <sys/ipc.h>
#include <sys/stat.h>
#include <sys/msg.h>
#include <semaphore.h>

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

int main(void)
{
	int msgid; //保存消息队列id
	sem_t *sem1 = NULL,*sem2 = NULL;//保存信号量地址
	ssize_t rcv_bytes;//保存从队列中读取的字节数
	int ret;

	msgid = msgget((key_t)123,IPC_CREAT|0666);
	if(msgid < 0 ){
		perror("creat a msg queue fail");
		return -1;
	}
	printf("msgid=%d\n",msgid);
	//创建或者打开POSIX有名信号量
	sem1 = sem_open("sem1",O_CREAT|O_RDWR,0666,1);
	if(sem1 == SEM_FAILED){
		perror("open sem1 fail");
		return -1;
	}
	//创建或者打开POSIX有名信号量
	sem2 = sem_open("sem2",O_CREAT|O_RDWR,0666,0);
	if(sem2 == SEM_FAILED){
		perror("open sem2 fail");
		return -1;
	}
	struct msgbuf msg_to_rcv;
	while(1){
		sem_wait(sem2);
		ret = msgrcv(msgid,&msg_to_rcv,100,1,0);
		if(ret < 0){
			perror("receive msg from queue fail");
			return -3;
		}
		rcv_bytes = ret;
		printf("received a msg[%d bytes]:%s\n",(int)rcv_bytes,msg_to_rcv.mtext);
		sem_post(sem1);
		if(strncmp("quit",msg_to_rcv.mtext,4)==0){
			printf("p1 readys to quit\n");
			break;
		}
	}
	return 0;
}

Makefile

all:
	gcc -o p1 p1.c -lrt -pthread	
	gcc -o p2 p2.c -lrt -pthread	
clean:
	rm -rf p1 p2

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值