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