首页 > 解决方案 > Fork() 带有信号的子进程

问题描述

我必须派生两个阻止 SIGINT 命令的子进程,但其中一个应该在接收到 SIGTERM 信号时取消阻止它,而另一个子进程和父进程由于相同的 SIGTERM 信号而打印它们的 PID。第二个子进程应立即终止,但父进程应等待其子进程结束然后停止。

我刚开始在 Linux 中学习 C 编程,我并不真正了解分叉和信号是如何工作的。据我了解,到目前为止我编写的这段代码将分叉一个进程,并且子进程将阻止 Ctrl-C 命令,除非我用 kill -9 pid杀死它,否则整个过程将永远运行。

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>

void handler(int n) {
    write(STDOUT_FILENO, "I won't die!! Haha\n",13);
}

int main()
{
    pid_t pid = fork();
    if (pid < 0) {
        perror("Fork() error!");
        exit(-1);
    }
    if (pid == 0)
        signal(SIGINT,handler);
    while(1) {
        printf("Wasting the iteration. %d\n", getpid());
        sleep(1);
    }
    return 0;
}

标签: linuxprocesssignalsfork

解决方案


不确定是否要分叉多个进程,因为我从未这样做过。就 SIGTERM 而言,您需要一个回调来处理终止信号。以下是我在编写的许多服务中使用的一个:

/***************************************************************************************************
 * Function signal_callback_handler - allows for a graceful shutdown process.
 * *************************************************************************************************/
void signal_callback_handler(int signum) {
    //here we receive some sort of notification to terminate.
    //Log this event and change the state of the process control variable
    //so that the main processing loop knows to stop
    syslog(LOG_NOTICE, "Recived signal to shutdown - Signal %d", signum);
    //put code here to do preshutdown clean up, terminating threads, etc....
}

然后,您需要为要处理的每个终止信号注册回调。以下是我在 fork 之前放在 main 函数中的那些:

if (signal(SIGINT, signal_callback_handler) == SIG_ERR) {
    syslog(LOG_CRIT, "An error occurred while setting SIGINT signal handler.");
    return(EXIT_FAILURE);
}
if (signal(SIGUSR1, signal_callback_handler) == SIG_ERR) {
    syslog(LOG_CRIT, "An error occurred while setting SIGUSR1 signal handler.");
    return(EXIT_FAILURE);
}
if (signal(SIGUSR2, signal_callback_handler) == SIG_ERR) {
    syslog(LOG_CRIT, "An error occurred while setting SIGUSR signal handler.");
    return(EXIT_FAILURE);
}
if (signal(SIGTERM, signal_callback_handler) == SIG_ERR) {
    syslog(LOG_CRIT, "An error occurred while setting SIGTERM signal handler.");
    return(EXIT_FAILURE);
}
if (signal(SIGTSTP, signal_callback_handler) == SIG_ERR) {
    syslog(LOG_CRIT, "An error occurred while setting SIGTSTP signal handler.");
    return(EXIT_FAILURE);
}

推荐阅读