首页 文章

C中的信号处理

提问于
浏览
1

我制作了以下程序来学习 SIG_SETMASK 的行为 .

以下程序应该阻止 SIGINT 中断信号,直到 func() 函数调用

sigprocmask(SIG_SETMASK,&fOnemask,NULL);

在fOnemask为空的情况下,cuz之前没有信号存储在sigset中 . 但正如我所说的那样

sigprocmask(SIG_SETMASK,&fTwoCmask,NULL);

在返回前的 func2() 函数内,其中fTwomask包含 func() 函数生成的上一个信号列表,程序开始接收信号,当SIGINT通过时程序被中断 .

为什么会这样?

void func();
void func2();

int main()
{
    int childpid,child;
    childpid=fork();

    if(childpid==0)
    {
        func();
    }

    while(wait(NULL)>0);
    return 0;
}

void func()
{
    sigset_t sigmask,fOnemask;
    sigemptyset(&sigmask);
    sigaddset(&sigmask,SIGINT);
    sigprocmask(SIG_SETMASK,&sigmask,&fOnemask);

    func2();

    int i;
    for(i=0;i<10;i++)
    {
        sleep(1);
        printf("%d\n",i);
    }

    sigprocmask(SIG_SETMASK,&omask,NULL);
    printf("returning from func\n");

}

void func2()
{
    sigset_t sigmask,fTwomask;
    sigemptyset(&sigmask);
    sigfillset(&sigmask);
    sigprocmask(SIG_SETMASK,&sigmask,&fTwomask);

    int i;
    for(i=0;i<10;i++)
    {
        sleep(1);
        printf("%d\n",i);
    }

    sigprocmask(SIG_SETMASK,&fTwomask,NULL);
    printf("func2 ending\n");
}

enter image description here

1 回答

  • 0

    父进程被SIGINT中断,因为你从不在父进程中为SIGINT设置任何信号处理,所以它被设置为SIG_DFL(可能,除非你在shell中转换了中断处理,这是不太可能的),所以流程终止 .

    你是对的;发送中断时shell不会死亡 . 那是因为炮弹非常小心,以确保它们不被中断杀死 .


    对主要问题的评论之一是:

    如果我在main函数的sigset_t对象中添加一个信号,然后从main调用foo() . 然后我在foo()的另一个sigset_t对象中添加一个信号,如sigprocmask(SIG_SETMASK,&foomask和oldmask) . 当我调用sigprocmask(SIG_SETMASK,&oldset,NULL)时,sigprocmask(SIG_SETMASK,&oldset,NULL)会做什么?

    你的评论(问题)充其量是令人困惑的;评论不是编辑问题的最佳方式 .

    据我了解,你问的是:

    static void foo(void);
    
    int main(void)
    {
        sigset_t mainmask;
        sigemptyset(&mainmask);
        sigaddset(&mainmask, SIGINT);
    
        // No call to sigprocmask() here...
    
        foo();
        return(0);
    }
    
    static void foo(void)
    {
        sigset_t foomask;
        sigset_t oldmask;
        sigset_t oldset;     // Uninitialized
        sigemptyset(&foomask);
        sigaddset(&foomask, SIGQUIT);  // Different signal
        if (sigprocmask(SIG_SETMASK, &foomask, &oldmask) != 0)
            ...process error...
        if (sigprocmask(SIG_SETMASK, &oldset, NULL) != 0)
            ...process error...
        ...other code, presumably...
    }
    

    这就是评论中写的内容,尽我所能 . 因为 oldset 未被初始化,你会遭受GIGO(垃圾进入,垃圾出);没有人可以说会发生什么,因为行为是未定义的 .

    如果你的意思是 oldmask 而不是 oldset ,那么 foo() 可能看起来像:

    static void foo(void)
    {
        sigset_t foomask;
        sigset_t oldmask;
        sigemptyset(&foomask);
        sigaddset(&foomask, SIGQUIT);  // Different signal
        if (sigprocmask(SIG_SETMASK, &foomask, &oldmask) != 0)
            ...process error...
        if (sigprocmask(SIG_SETMASK, &oldmask, NULL) != 0)
            ...process error...
        ...other code, presumably...
    }
    

    然后第二个 sigprocmask() 撤消第一次调用 sigprocmask() 所做的更改 . 请记住,SIG_SETMASK选项意味着'set the process signal mask to exactly the mask in the second argument'(除非第二个参数为null,在这种情况下,第三个参数不应该为空,并且它在第一个参数中不会't matter what',因为它成为调用以查找当前掩码而不更改任何内容) .

相关问题