C中的信号处理 - 中断中断

And*_*dna 5 c signals

当我的程序同时处理其他信号时,我想知道是否有可能被信号中断,我试图用以下方法模拟它:

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

void sig_output()
{
    sigset_t set;
    sigprocmask(0,NULL,&set);
    printf("currently blocking:");
    if (sigismember(&set,SIGUSR1))
        printf("\nSIGUSR1");
    if(sigismember(&set,SIGUSR2))
        printf("\nSIGUSR2");
    printf("\n");
    return ;
}

void sig_handler(int sig)
{
    raise(SIGUSR1);    
    printf("start\n");
    if (sig==SIGUSR1)
        printf("SIGUSR1\n");
    else if (sig==SIGUSR2)
        printf("SIGUSR2\n");
    printf("end\n");
    return ;
}

void other_sig_handler(int sig)
{  
    printf("start - other\n");
    if (sig==SIGUSR1)
        printf("SIGUSR1\n");
    else if (sig==SIGUSR2)
        printf("SIGUSR2\n");
    printf("end - other\n");
    return ;
}

int main()
{
    sig_output();
    struct sigaction a;
    a.sa_handler=sig_handler;
    a.sa_flags=0;
    sigset_t set,old;
    //blocking SIGUSR1,SIGUSR2
    sigemptyset(&set);
    sigaddset(&set,SIGUSR1);
    sigaddset(&set,SIGUSR2);
    printf("blocking SIGUSR1, SIGUSR2\n");
    sigprocmask(SIG_SETMASK,&set,&old);
    sig_output();
    //adding handles for SIGUSR1,SIGUSR2
    sigemptyset(&(a.sa_mask));
    sigaction(SIGUSR1,&a,NULL);
    a.sa_handler=other_sig_handler;
    sigaction(SIGUSR2,&a,NULL);
    printf("poczatek wysylania \n");
    raise(SIGUSR1);
    raise(SIGUSR2);
    raise(SIGUSR1);
    printf("using sigsuspend\n");
    sigsuspend(&old);
    printf("end of program\n");
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

每次我运行这个程序,我得到

currently blocking:
blocking SIGUSR1, SIGUSR2
currently blocking:
SIGUSR1
SIGUSR2
raising
using sigsuspend
start - other
SIGUSR2
end - other
start
SIGUSR1
end
end of program
Run Code Online (Sandbox Code Playgroud)

总是这样吗?

gee*_*aur 6

引用sigaction(2)联机帮助页:

信号例程通常使用导致其调用被阻止的信号执行,但是其他信号可能仍然发生.全局信号掩码定义当前阻止传递到进程的信号集.进程的信号掩码从其父进程(通常为空)初始化.可以通过sigprocmask(2)呼叫更改,也可以在将信号传递给流程时更改.

您可以控制信号是否在带有SA_NODEFER标志的信号处理程序中自动阻止.


tor*_*rek 6

据我所知,这些特定待处理信号的传递顺序并未定义.然而,信号(主要是,有一个例外SIGCLD,这是传统的"作弊"做)"不排队",除了实时信号.非排队方面意味着如果您阻止信号X,然后raise两次(如上所述SIGUSR1),您只能将其传送一次.

至少在一个系统(MacOS)上记录的唯一排序是:

If multiple signals are ready to be delivered at the same time, any signals that
could be caused by traps are delivered first.
Run Code Online (Sandbox Code Playgroud)

(这些都是像SIGSEGVSIGBUS.)在一般情况下,可以通过使用阻挡遮罩的信号的控制传递的顺序:解除在某些时候任何特定的信号(S)和那些是可在该点处被递送的那些.

如果没有设置SA_NODEFER,处理程序入口处的阻塞掩码将始终阻止处理程序处理的任何信号,这样您就不必担心递归.

特殊情况SIGCLD来自System V,它最初是通过SIG_DFL在每次SIGCLD交付时重置处理程序来实现的.(实际上,SysV用所有信号做到了这一点,有效地实现SA_RESETHAND了你是否想要它.)默认动作是丢弃信号,就好像处理程序一样SIG_IGN.这当然会在多个子进程在处理程序完成之前完成时创建竞争条件.但是,SysV人员不是使用块/解块模型,而是SIGCLD处理黑客攻击:在处理程序结束时,您将调用signal(SIGCLD, handler);修复处理程序.此时,如果有任何已退出的子项尚未被wait删除,SysV将立即生成一个新的 SIGCLD,并且您的处理程序将以递归方式输入.这使得它看起来好像排队了,而没有实际排队.

有关Linux信号的更多信息,请参阅(例如)http://www.kernel.org/doc/man-pages/online/pages/man7/signal.7.html.