简体   繁体   English

使用C中的子进程发送和处理信号时遇到麻烦

[英]Trouble sending and handling signals with children processes in C

The parent process forks two children, each replace SIGUSR1 and SIGUSR2 signal respectively. 父进程派生两个孩子,每个孩子分别替换SIGUSR1SIGUSR2信号。

The parent process replace SIGINT signal, on catching it, send SIGUSR1 and SIGUSR2 to its children respectively. 父进程替换SIGINT信号,在捕获它时,分别将SIGUSR1SIGUSR2发送到其子级。

The expected output when Ctrl-C is pressed should be: 按下Ctrl-C时的预期输出应为:

Ctrl+C is pressed。
received SIGUSR1 signal
received SIGUSR2 signal

But on Ctrl-C I've got 但是在Ctrl-C上

Ctrl+C is pressed。

I have no idea why sig_handler_1 and sig_handler_2 are not excuted. 我不知道为什么sig_handler_1sig_handler_2进行sig_handler_2

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <signal.h>
void fun_ctrl_c(int);
void sig_handler_1(int);
void sig_handler_2(int);
pid_t pid1;
pid_t pid2;
int status;

int main() {
    pid1 = fork();
    if (pid1 == 0) {    // child 1
        // avoid to be killed
        (void) signal(SIGINT, SIG_IGN);
        // replace SIGUSR1
        (void) signal(SIGUSR1, sig_handler_1);
        raise(SIGSTOP);
    } else {
        pid2 = fork();
        if (pid2 == 0) {    // child 2
            // avoid to be killed
            (void) signal(SIGINT, SIG_IGN);
            // replace SIGUSR2
            (void) signal(SIGUSR2, sig_handler_2);
            raise(SIGSTOP);
        } else {    // parent
            (void) signal(SIGINT, fun_ctrl_c);
            waitpid(-1, &status, 0);
        }
    }
    return 0;
}

void fun_ctrl_c(int)
{
    printf("Ctrl+C is pressed。\n");
    kill(pid1 ,SIGUSR1);
    kill(pid2 ,SIGUSR2);
    (void) signal(SIGINT, SIG_DFL);
}

void sig_handler_1(int)
{
    printf("received SIGUSR1 signal\n");
}

void sig_handler_2(int)
{
    printf("received SIGUSR2 signal\n");
}

Your problem is that you do raise(SIGSTOP); 您的问题是您确实raise(SIGSTOP); in the child processes, so they're stopped and cannot respond to signals at all. 在子进程中,因此它们被停止并且根本无法响应信号。

Replace that with pause(); 替换为pause(); — the code then works. —代码便可以正常工作。

#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <unistd.h>

void fun_ctrl_c(int);
void sig_handler_1(int);
void sig_handler_2(int);

pid_t pid1;
pid_t pid2;

int main(void)
{
    pid1 = fork();
    if (pid1 == 0)
    {
        (void) signal(SIGINT, SIG_IGN);
        (void) signal(SIGUSR1, sig_handler_1);
        pause();
        printf("PID %d exiting\n", (int)getpid());
    }
    else if ((pid2 = fork()) == 0)
        {
            (void) signal(SIGINT, SIG_IGN);
            (void) signal(SIGUSR2, sig_handler_2);
            pause();
            printf("PID %d exiting\n", (int)getpid());
        }
        else
        {
            (void) signal(SIGINT, fun_ctrl_c);
            int status;
            int pid;
            printf("Interrupt me!\n");
            while ((pid = waitpid(-1, &status, 0)) != -1)
                printf("Child %d exited with status 0x%.4X\n", pid, status);
            printf("Parent %d exiting\n", (int)getpid());
        }
    return 0;
}

void fun_ctrl_c(int signum)
{
    printf("Ctrl+C is pressed。Received SIGINT (%d) signal\n", signum);
    kill(pid1, SIGUSR1);
    kill(pid2, SIGUSR2);
    (void) signal(SIGINT, SIG_DFL);
}

void sig_handler_1(int signum)
{
    printf("received SIGUSR1 (%d) signal\n", signum);
}

void sig_handler_2(int signum)
{
    printf("received SIGUSR2 (%d) signal\n", signum);
}

Sample run (I called the program sigintusr12 ): 运行示例(我称为程序sigintusr12 ):

$ ./sigintusr12
Interrupt me!
^CCtrl+C is pressed。Received SIGINT (2) signal
received SIGUSR2 (31) signal
received SIGUSR1 (30) signal
PID 31184 exiting
PID 31183 exiting
Child 31184 exited with status 0x0000
Child 31183 exited with status 0x0000
Parent 31182 exiting
$

Note that you're not strictly supposed to use printf() (and many other functions, especially those that might need to allocate memory) inside a signal handler. 请注意,您不严格应该在信号处理程序中使用printf() (以及许多其他函数,尤其是那些可能需要分配内存的函数)。 It'll work OK here, but it is not good practice. 在这里可以正常工作,但这不是一个好习惯。 See How to avoid using printf() in a signal handler? 请参阅如何避免在信号处理程序中使用printf() for more information. 欲获得更多信息。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM