信号处理用C - 中断中断(Signal handling in C - interrupt in

2019-06-23 12:13发布

我在想,如果有可能,当我的程序在同一时间处理其它信号由信号中断,我试着用模拟它:

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

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

currently blocking:
blocking SIGUSR1, SIGUSR2
currently blocking:
SIGUSR1
SIGUSR2
raising
using sigsuspend
start - other
SIGUSR2
end - other
start
SIGUSR1
end
end of program

是不是总是这样?

Answer 1:

引述sigaction(2)手册页:

信号例程通常与引起它们的调用阻塞信号执行,但仍有可能发生的其他信号。 全局信号掩模限定的集合的当前从输送到处理阻塞的信号。 用于处理信号掩码是从它的父的(通常是空的)进​​行初始化。 它可以与一个被改变sigprocmask(2)呼叫时,或者当一个信号被发送到该过程。

您可以控制信号是否被自动阻止与它的信号处理程序SA_NODEFER标志。



Answer 2:

其中这些特定的待处理信号传送的顺序不是,据我所知,所定义。 然而, 信号 (主要是,有一个例外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.

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

如果不设置SA_NODEFER ,在进入到您的处理总是会阻止任何信号处理程序正在处理,这样你就不必担心递归阻断掩膜。

对于特殊情况SIGCLD来自System V的,最初通过复位处理程序来实现这个SIG_DFL每个SIGCLD交货。 (事实上,SysV的这样做的所有信号,有效地实施SA_RESETHAND不管你愿意与否。)默认行为是丢弃该信号,因为如果处理程序是SIG_IGN 。 这当然创造竞争条件,当多个子进程结束的处理程序可以做它的事了。 取而代之的是块/疏通模型,不过,放在一个黑客SysV的人:在你结束SIGCLD处理程序,只需要调用signal(SIGCLD, handler); 修复了处理程序。 在这一点上,如果有任何离开的孩子,那时还没有wait -ed的,SysV的会立即生成一个新的 SIGCLD ,你的处理程序将被递归进入。 这使得它看起来好像信号排队,不排队实际上他们。

欲了解更多关于Linux的信号,见(例如) http://www.kernel.org/doc/man-pages/online/pages/man7/signal.7.html 。



文章来源: Signal handling in C - interrupt in interrupt
标签: c signals