簡體   English   中英

使用C中的子進程發送和處理信號時遇到麻煩

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

父進程派生兩個孩子,每個孩子分別替換SIGUSR1SIGUSR2信號。

父進程替換SIGINT信號,在捕獲它時,分別將SIGUSR1SIGUSR2發送到其子級。

按下Ctrl-C時的預期輸出應為:

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

但是在Ctrl-C上

Ctrl+C is pressed。

我不知道為什么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");
}

您的問題是您確實raise(SIGSTOP); 在子進程中,因此它們被停止並且根本無法響應信號。

替換為pause(); —代碼便可以正常工作。

#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);
}

運行示例(我稱為程序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
$

請注意,您不嚴格應該在信號處理程序中使用printf() (以及許多其他函數,尤其是那些可能需要分配內存的函數)。 在這里可以正常工作,但這不是一個好習慣。 請參閱如何避免在信號處理程序中使用printf() 欲獲得更多信息。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM