信号处理程序中fork()的父子进程同步安全实现咨询
信号处理程序中fork后父子进程同步的安全实现方式
你的核心问题是信号处理程序中不能使用普通互斥锁(这类锁操作不在异步安全函数列表里),但要实现父进程完成任务后子进程再执行后续逻辑,下面是两种可靠的异步安全实现方式:
方法一:用匿名管道同步
管道的read()和write()属于异步安全函数,可在信号处理程序里安全使用,实现逻辑如下:
- 父进程在
fork()前创建一对匿名管道 - 父进程分支先执行
build_house(),完成后往管道写一个标记数据(比如一个字节) - 子进程分支先执行
play_in_yard(),然后从管道读数据——读操作会阻塞直到父进程写完,之后再执行enter_house()
示例代码:
#include <unistd.h> #include <stdlib.h> void signal_handler(int sig) { int pipefd[2]; if (pipe(pipefd) == -1) { _exit(1); } pid_t child_pid = fork(); if (child_pid != 0) { // 父进程:关闭读端 close(pipefd[0]); build_house(); // 写一个字节标记任务完成 char dummy = '1'; write(pipefd[1], &dummy, 1); close(pipefd[1]); } else { // 子进程:关闭写端 close(pipefd[1]); play_in_yard(); // 等待父进程的信号,阻塞直到读到数据 char dummy; read(pipefd[0], &dummy, 1); close(pipefd[0]); enter_house(); _exit(0); } }
方法二:用用户自定义信号同步
kill()和sigwait()属于异步安全操作,也能实现同步:
- 父进程
fork()后,完成build_house()时,用kill()给子进程发送自定义信号(比如SIGUSR1) - 子进程先执行
play_in_yard(),然后通过sigwait()等待信号,收到后执行enter_house()
示例代码:
#include <signal.h> #include <unistd.h> #include <stdlib.h> void signal_handler(int sig) { pid_t child_pid = fork(); if (child_pid != 0) { // 父进程 build_house(); // 给子进程发信号 kill(child_pid, SIGUSR1); wait(NULL); } else { // 子进程:设置信号掩码,只等待SIGUSR1 sigset_t set; sigemptyset(&set); sigaddset(&set, SIGUSR1); // 阻塞等待信号 int sig_caught; sigwait(&set, &sig_caught); play_in_yard(); enter_house(); _exit(0); } }
注意事项
- 信号处理程序里绝对不能调用非异步安全函数,错误处理尽量用
_exit()而不是exit() - 用管道时要注意关闭未使用的文件描述符,避免资源泄漏
- 用信号时要注意信号掩码的设置,避免其他信号干扰等待逻辑
内容的提问来源于stack exchange,提问作者user2766918
相关产品推荐
相关产品推荐

