C语言中SIGINT终止子进程时保持父进程存活的实现方法
C语言SIGINT信号仅终止子进程保留父进程的实现方案
该需求可以实现,你提到的「为父进程设置SIGINT信号处理函数、令父进程忽略SIGINT」的方案是可行的,只需要额外处理子进程的信号继承逻辑即可。
默认情况下,用户在终端按下Ctrl+C产生的SIGINT信号会发送给整个前台进程组,父进程和其创建的子进程都属于同一个前台进程组,默认都会收到SIGINT信号,信号的默认动作是终止进程,因此默认情况下父子进程都会同时退出。
核心实现逻辑
- 父进程注册SIGINT信号的处理规则为忽略,或者注册空的自定义处理函数,让父进程收到SIGINT时不执行默认的终止动作
- 父进程调用
fork()创建子进程后,子进程需要立即将SIGINT的处理规则重置为系统默认动作SIG_DFL(子进程会默认继承父进程的信号处理配置,如果不重置,子进程也会忽略SIGINT无法被终止) - 父进程需要监听子进程的退出状态,回收子进程资源避免僵尸进程
完整代码示例
#include <stdio.h> #include <unistd.h> #include <signal.h> #include <sys/wait.h> #include <sys/types.h> int main() { // 父进程设置忽略SIGINT信号 signal(SIGINT, SIG_IGN); printf("父进程启动,PID:%d,按下Ctrl+C仅会终止子进程\n", getpid()); while(1) { pid_t pid = fork(); if (pid < 0) { perror("fork失败"); return 1; } else if (pid == 0) { // 子进程:重置SIGINT为默认处理动作,收到SIGINT就会终止 signal(SIGINT, SIG_DFL); printf("子进程启动,PID:%d,正在运行...\n", getpid()); // 子进程模拟业务逻辑 while(1) { sleep(1); } return 0; } else { // 父进程:等待子进程退出,回收资源 int status; waitpid(pid, &status, 0); if (WIFSIGNALED(status)) { printf("子进程%d被信号%d终止,父进程继续运行\n", pid, WTERMSIG(status)); } // 等待2秒后可重新创建子进程,也可以执行其他父进程逻辑 sleep(2); printf("父进程准备重新创建子进程...\n"); } } return 0; }
运行效果说明
编译运行代码后,按下Ctrl+C会看到子进程被终止,父进程不会退出,等待2秒后会重新启动新的子进程。
注意事项
- 如果需要父进程对SIGINT做额外处理(比如收到SIGINT时先做清理再选择是否退出),可以将
signal(SIGINT, SIG_IGN)替换为自定义的信号处理函数,不需要忽略也能实现父进程不终止。 - 子进程如果调用
exec()系列函数加载新的程序,exec执行后所有被设置为忽略/自定义处理的信号都会重置为默认动作,这种情况下子进程可以不用手动重置SIGINT的处理规则。 - 多次调用
signal()设置同一信号的处理规则会覆盖之前的配置,可根据业务需要灵活调整。
内容的提问来源于stack exchange,提问作者LYH
相关产品推荐
相关产品推荐

