系统编程练习题----使用消息队列实现两个进程之间的通信
题目
要求进程A创建一条消息队列之后向进程B发送SIGUSR1信号,进程B收到该信号之后打开消息队列并写入一段信息作为消息写入到消息队列中,要求进程B在写入消息之后,发SIGUSR2信号给进程A,进程A收到该信号则从消息队列中读取消息并输出消息正文的内容。
思路
- 通过进程A创建的消息队列,实现进程A与进程B之间的PID交换
- 通过kill指令完成进程A与进程B之间的信号交互,并通过状态机实现步骤的进行
- 进程A收到进程B的信号后,从消息队列中读出消息,并完成显示
代码展示
进程A
/*******************************************************************
*
* file name: process_A.c
* author : [email protected]
* date : 2024/05/27
* function : 该案例是掌握进程通信方式,主要是学习信号和消息队列的使用
* note : None
* version :
*
* CopyRight (c) 2023-2024 [email protected] All Right Reseverd
*
* *****************************************************************/
/****************************头文件**************************************/
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <errno.h>
#include <string.h>
#include <signal.h>
#include <sys/msg.h>
#include <stdlib.h>
#include <unistd.h>
/****************************结构体**************************************/
struct msgbuf
{
long mtype; /* message type, must be > 0 */
int mtext; /* message data */
};
/****************************全局变量**************************************/
volatile int flag; //作为状态机条件
/********************************************************************
*
* name : msg_get
* function : 改函数用于获取进程B发送的信号
* pqram :
* @signum : 捕捉到的信号类型
*
* retval : none
* author : [email protected]
* date : 2024/05/27
* note : none
* version :
*
* *****************************************************************/
void msg_get(int signum)
{
if(signum == SIGUSR1)
{
//改变标志量,从消息队列中读取进程B的pid
flag = 1;
}
else if(signum == SIGUSR2)
{
//改变标志量,从消息队列中读取进程B发送的消息
flag = 0;
}
}
int main(int argc, char const *argv[])
{
//捕捉进程B发送的信号,再从消息队列中获取进程B的pid
signal(SIGUSR1, msg_get);
//捕捉进程B发送的信号,再从消息队列中获取进程B发送的消息
signal(SIGUSR2, msg_get);
/****创建一条消息队列****/
//1) 获取消息队列唯一键值(key)
key_t key = ftok(".", 0xffffff01);
//2) 定义一个变量用于存储消息队列id,创建一条消息队列
int msg_id = msgget(key, IPC_CREAT | 0644);
if(msg_id == -1)
{
fprintf(stderr, "msgget error , errno: %d, %s\n", errno, strerror(errno));
exit(-1);
}
/****发送SIGUSR1信号给进程B****/
// 通过消息队列完成A,B进程的pid交换
//1. 将进程A的pid写入消息队列中
struct msgbuf msg_pid;
msg_pid.mtype = 1;
msg_pid.mtext = getpid();
msgsnd(msg_id, &msg_pid, 4, 0);
//2. 捕捉进程B发送的SIGUSR1信号
while(flag == 0);
// 3. 从消息队列中读取进程B的pid
struct msgbuf msg_pid_B;
msgrcv(msg_id, &msg_pid_B, 4, 1, IPC_NOWAIT);
//4. 发送SIGUSR1信号给进程b
kill(msg_pid_B.mtext, SIGUSR1);
/****接收到进程B的信号后,从消息队列中读出消息并输出****/
while(flag);
struct msgbuf msg_num;
msgrcv(msg_id, &msg_num, 4, 2, IPC_NOWAIT);
printf("The information received from process B is %d\n", msg_num.mtext);
return 0;
}
进程B
/*******************************************************************
*
* file name: process_B.c
* author : [email protected]
* date : 2024/05/27
* function : 该案例是掌握进程通信方式,主要是学习信号和消息队列的使用
* note : None
* version :
*
* CopyRight (c) 2023-2024 [email protected] All Right Reseverd
*
* *****************************************************************/
/****************************头文件**************************************/
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <errno.h>
#include <string.h>
#include <signal.h>
#include <sys/msg.h>
#include <stdlib.h>
#include <unistd.h>
/****************************结构体**************************************/
struct msgbuf
{
long mtype; /* message type, must be > 0 */
int mtext; /* message data */
};
/****************************全局变量**************************************/
volatile int flag = 1; //作为状态机条件
/********************************************************************
*
* name : msg_get
* function : 改函数用于获取进程A发送的信号
* pqram :
* @signum : 捕捉到的信号类型
*
* retval : none
* author : [email protected]
* date : 2024/05/27
* note : none
* version :
*
* *****************************************************************/
void msg_get(int signum)
{
if(signum == SIGUSR1)
{
//改变标志量,从消息队列中读取进程A的pid
flag = 0;
}
}
int main(int argc, char const *argv[])
{
//捕捉进程A发送的信号,再从消息队列中获取进程B的pid
signal(SIGUSR1, msg_get);
/****打开一条消息队列****/
//1) 获取消息队列唯一键值(key)
key_t key = ftok(".", 0xffffff01);
//2) 定义一个变量用于存储消息队列id,创建一条消息队列
int msg_id = msgget(key, IPC_CREAT | 0644);
if(msg_id == -1)
{
fprintf(stderr, "msgget error , errno: %d, %s\n", errno, strerror(errno));
exit(-1);
}
struct msgbuf msg_pid_a;
/****从消息队列中读取进程A的pid,并将进程B的pid写入消息队列中***/
msgrcv(msg_id, &msg_pid_a, 4, 1, IPC_NOWAIT);
//将进程B的pid写入消息队列
struct msgbuf msg_pid_b;
msg_pid_b.mtype = 1;
msg_pid_b.mtext = getpid();
msgsnd(msg_id, &msg_pid_b, 4, 0);
/****发送SIGUSR1信号给进程A****/
kill(msg_pid_a.mtext, SIGUSR1);
/****等待接收进程A的SIGUSR1信号****/
while(flag == 1);
/****接收到进程A的信号后,将数据写入消息队列中***/
struct msgbuf msg_num;
msg_num.mtype = 2;
msg_num.mtext = 66666;
msgsnd(msg_id, &msg_num, 4, 0);
/****发送SIGUSR2信号给进程A****/
kill(msg_pid_a.mtext, SIGUSR2);
return 0;
}