1

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

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

     sigprocmask(SIG_SETMASK,&fOnemask,NULL);

其中 fOnemask 是空的,因为在它之前没有信号存储在 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");
}

在此处输入图像描述

4

1 回答 1

0

父进程被 SIGINT 中断,因为您从未在父进程中为 SIGINT 设置任何信号处理,因此将其设置为 SIG_DFL(可能,除非您在 shell 中关闭了中断处理,这不太可能),所以进程终止。

你是对的; 发送中断时,shell 不会死。这是因为 shell 非常注意确保它们不会被中断杀死。


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

如果我sigset_t在函数中的对象中添加一个信号main,然后foo()main. 然后我在另一个sigset_t本地对象中添加一个信号到foo()like 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(garbage in,garbage out);没有人能说会发生什么,因为行为是未定义的。

如果您的意思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 选项的意思是“将进程信号掩码设置为第二个参数中的掩码”(除非第二个参数为空,在这种情况下,第三个参数不应为空,并且第一个参数中的内容无关紧要参数,因为它变成了在不更改任何内容的情况下找出当前掩码的调用)。

于 2013-01-06T17:11:10.320 回答