湘潭大学 - Linux信号实验

一、实验内容

设计一个程序,该程序有一个父进程和三个子进程,初始阶段输出如下内容:
Parent-hello-0
Child1-hello-1
Child2-hello-2
Child3-hello-3
Parent-hello-4
依次类推,每条信息间间隔1s。顺序不能乱。
当程序运行一段时间后,按下CTRL+C,此时输出如下内容:
Child3-finished
Child2-finished
Child1-finished
Parent-finished
每条信息间隔1s。顺序不能乱。(提示: 用signal 捕捉信号,kill发送信号)

二、实验代码

#include <signal.h>
#include <unistd.h>
#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ipc.h>
#include <sys/types.h>
#include <sys/msg.h>

int status = -1; //当前运行进程状态
key_t key;
int msgid;
typedef struct{
	long type;
	int num;
} Msg;
Msg msg, rcv; //消息

void func_kill(int sig)
{
	if (status == 0) {
		msgrcv(msgid, &rcv, sizeof(rcv) - sizeof(rcv.type), 1, 0);
		printf("Parent-hello-%d\n", rcv.num);
	} else {
		msgrcv(msgid, &rcv, sizeof(rcv) - sizeof(rcv.type), 1, 0);
		printf("Child%d-hello-%d\n", status, rcv.num);
	}
	msg.num = rcv.num + 1; //加1
	msg.type = 1;
	msgsnd(msgid, &msg, sizeof(msg) - sizeof(msg.type), 0);
}
void func_back(int sig)
{
	sleep(4 - status);
	if (status == 0) {
		printf("Parent-finished!\n");
	} else {
		printf("Child%d-finished!\n", status);
	}
	msgctl(msgid, IPC_RMID, NULL); //删除消息队列
	signal(SIGINT, SIG_DFL);
	exit(0);
}
int main()
{
	pid_t pid[4] = {0, 1, 2, 3};
	int i;
	pid[0] = getpid();
	key = ftok("/home/china", '6');
	msgid = msgget(key, IPC_CREAT | 0777); //创建消息队列
	for (i = 1; i < 4; i++) {
		pid[i] = fork(); // 创建子进程
		sleep(1);
		if (pid[i] < 0) {
			printf("The fork is error!\n");
			exit(0);
		} else if (pid[i] == 0) {
			break;
		}
	}
	signal(SIGINT, func_back);
	while (1) {
		if (pid[1] > 0 && pid[2] > 0 && pid[3] > 0) {
			signal(SIGCONT, func_kill); //接受唤醒信号
			if (status == -1) {
				status = 0;
				sleep(2);
				printf("Parent-hello-0\n");
				msg.type = 1;
				msg.num = 1;
				msgsnd(msgid, &msg, sizeof(msg) - sizeof(msg.type), 0);
				//发送消息
			}
			sleep(1);
			kill(pid[3], SIGCONT); //发送唤醒信号
			pause();
		} else if (pid[1] > 0 && pid[2] > 0 && pid[3] == 0) {
			signal(SIGCONT, func_kill);
			if (status == -1) {
				status = 1;
				pause();
			}
			sleep(1);
			kill(pid[2], SIGCONT);
			pause();
		} else if (pid[1] > 0 && pid[2] == 0 && pid[3] > 0) {
			signal(SIGCONT, func_kill);
			if (status == -1) {
				status = 2;
				pause();
			}
			sleep(1);
			kill(pid[1], SIGCONT);
			pause();
		} else if (pid[1] == 0 && pid[2] > 0 && pid[3] > 0) {
			signal(SIGCONT, func_kill);
			if (status == -1) {
				status = 3;
				pause();
			}
			sleep(1);
			kill(pid[0], SIGCONT);
			pause();
		}
	}
	return 0;
}

此代码参考的湘大好心学长的,这里以我有限的能力做下个人的理解
创建三个子进程,创建消息队列,在父进程和三个子进程中无限循环并接收唤醒信号,接收到唤醒信号后立马调用函数将信息加入消息队列,之后再把原始信息加1,同时函数中也打印出实验需求的数据;执行完成后睡眠1秒,然后唤醒下一个进程,当前进程则调用pause()函数停止,等待下一次唤醒;其他进程同上,当监听到ctrl + C时,调用结束函数,四个进程,每个进程睡眠时间为4-(第几个),父进程为第0个。然后删除消息队列。
实验效果图如下

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值