在C中处理信号

我做了以下程序来学习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"); } 

在这里输入图像说明

父进程被SIGINT中断,因为你从来没有在父进程中为SIGINT设置任何信号处理,所以它被设置为SIG_DFL(可能除非你已经在shell中处理中断,这是不太可能的),所以进程终止。

你是对的; 发送中断时,shell不会死亡。 这是因为炮弹需要非常小心,以确保它们不会被打断。


其中一个主要问题的评论是:

如果我在main函数的sigset_t对象中添加一个信号,然后从main调用foo() 。 然后,我在sigprocmask(SIG_SETMASK, &foomask, &oldmask) foo()这样的foo()另一个sigset_t对象中添加一个信号。 当我调用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选项的意思是“将进程信号掩码设置为第二个参数中的掩码”(除非第二个参数为null,在这种情况下,第三个参数不应该为null,并且不管它是什么因为它变成了调用来找出当前的面具而不改变任何东西)。