一、实验要求
- 在 Ubuntu 或 openEuler 中完成任务(推荐openEuler)
- 写一个父子进程通信程序。父进程每2秒向子进程发送SIGUSR2信号。子进程统计收到信号的次数,并在收到第5次时输出"Received 5 signals, child exit!",然后退出。父进程检测到子进程退出后(可通过SIGCHLD或wait),输出"Child terminated."并自身退出。
- 提交代码和运行结果截图或文本
二、实验过程
1、程序实现
test.c
c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <sys/wait.h>
int signal_count = 0; // 记录接收到的SIGUSR2信号的次数
// 子进程接收到SIGUSR2信号的处理函数
void sigusr2_handler(int sig) {
signal_count++; // 每接收到一个SIGUSR2信号,计数器加一
printf("Received signal %d times\n", signal_count);
// 如果接收到第5次信号,子进程退出
if (signal_count == 5) {
printf("Received 5 signals, child exit!\n");
exit(0); // 子进程退出
}
}
int main() {
pid_t pid = fork(); // 创建子进程
if (pid < 0) {
perror("fork failed");
exit(1);
}
if (pid == 0) { // 子进程
// 设置SIGUSR2信号的处理函数
signal(SIGUSR2, sigusr2_handler);
// 子进程无限循环,等待信号
while (1) {
pause(); // 等待信号
}
} else { // 父进程
sleep(1); // 给子进程一些时间来设置信号处理
// 每2秒向子进程发送SIGUSR2信号
for (int i = 0; i < 5; i++) {
sleep(2); // 每2秒发送一次
kill(pid, SIGUSR2); // 发送SIGUSR2信号给子进程
}
// 等待子进程退出(通过wait或SIGCHLD信号)
int status;
waitpid(pid, &status, 0); // 等待子进程结束
// 子进程退出后,父进程输出信息并退出
printf("Child terminated.\n");
exit(0);
}
return 0;
}
2、程序解析
-
信号处理:
- 子进程使用
signal(SIGUSR2, sigusr2_handler)
来设置 SIGUSR2 信号的处理函数。当子进程接收到 SIGUSR2 信号时,sigusr2_handler
函数会被调用,记录信号接收的次数,并在接收到第 5 次信号时退出子进程。 - 父进程每隔 2 秒通过
kill(pid, SIGUSR2)
向子进程发送一个 SIGUSR2 信号。
- 子进程使用
-
父子进程通信:
- 父进程通过
fork()
创建一个子进程。如果fork()
返回 0,则是子进程;如果返回一个正数,则是父进程,并且返回值是子进程的 PID。 - 父进程使用
kill()
向子进程发送信号,子进程则使用pause()
来等待并处理接收到的信号。
- 父进程通过
-
子进程退出:
- 子进程在接收到第 5 次 SIGUSR2 信号时,会输出 "Received 5 signals, child exit!" 并调用
exit(0)
退出。
- 子进程在接收到第 5 次 SIGUSR2 信号时,会输出 "Received 5 signals, child exit!" 并调用
-
父进程等待:
- 父进程通过
waitpid(pid, &status, 0)
等待子进程结束。子进程结束后,父进程会输出 "Child terminated." 并退出。
- 父进程通过
3、编译和运行

- 每隔 2 秒,父进程会发送一次 SIGUSR2 信号给子进程。
- 子进程收到 5 次信号后输出"Received 5 signals, child exit!"并退出。
- 父进程等待子进程退出后输出"Child terminated."并结束。
5、Gitee仓库
仓库链接:https://gitee.com/li-zhen1215/homework/tree/master/Week8/keshang3
