SIGUSR1父子进程通信问题:信号处理函数消息无法打印排查
问题分析与修复方案
核心问题点
信号处理注册时机错误
父进程先执行wait(NULL),再注册SIGUSR1的处理函数。第一个子进程会立即发送信号,此时父进程还没完成信号处理函数的注册,信号会触发默认行为(SIGUSR1默认会终止进程),后续逻辑根本无法执行;就算父进程没被终止,提前发送的信号也会直接丢失。错误使用
signal()函数
代码里用if(signal(SIGUSR1, handle_sigusr1))来判断是否收到信号,这是完全错误的用法。signal()的作用是设置信号处理函数,返回值是之前的处理函数指针,它不能检测信号是否到达。这段代码只会重复设置一次信号处理函数,不会在收到信号时执行里面的计数和打印逻辑。信号处理函数的描述逻辑错误
处理函数里的printf("Sending ready command...\n")描述反了,这个函数是父进程收到子进程信号时执行的,应该体现“收到就绪指令”的语义。未等待所有子进程退出
父进程只调用了一次wait(NULL),会导致其中一个子进程变成僵尸进程,需要调用两次或者用循环等待来回收所有子进程。
修正后的代码
#include<stdio.h> #include<unistd.h> #include<signal.h> #include<stdlib.h> #include<sys/wait.h> int x = 0; void handle_sigusr1(int sig){ x++; printf("Controller: Received ready command. Total %d\n", x); } int main(int args, char* argv[]){ int player0, player1; // 先注册信号处理函数,再创建子进程 struct sigaction sa = { 0 }; sa.sa_flags = SA_RESTART; sa.sa_handler = &handle_sigusr1; sigaction(SIGUSR1, &sa, NULL); player0 = fork(); if(player0 != 0){ player1 = fork(); } if(player0 == 0){ kill(getppid(), SIGUSR1); sleep(2); exit(0); } else if(player1 == 0){ sleep(3); kill(getppid(), SIGUSR1); sleep(2); exit(0); } else { // 等待两个子进程退出 wait(NULL); wait(NULL); printf("All children have exited.\n"); } return 0; }
修正说明
- 把信号处理函数的注册逻辑移到创建子进程之前,确保父进程在子进程发送信号前已经准备好处理信号。
- 把计数和打印逻辑移到信号处理函数里,这样每次收到SIGUSR1时都会执行计数和输出。
- 修正了处理函数里的输出文本,符合实际语义。
- 父进程调用两次
wait(NULL),确保两个子进程都被回收,避免僵尸进程。
内容的提问来源于stack exchange,提问作者Phillips
相关产品推荐
相关产品推荐

