Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/71.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C Linux如何区分定制信号处理程序的优先级?_C_Linux_Signals - Fatal编程技术网

C Linux如何区分定制信号处理程序的优先级?

C Linux如何区分定制信号处理程序的优先级?,c,linux,signals,C,Linux,Signals,上周我们有一次讲座,内容涉及操作系统(在本例中为Linux,在本例中为我们的学校服务器使用SUSE Linux 11)如何处理中断。值得注意的是,对于大多数信号,您可以捕获中断并定义自己的信号处理程序来运行,而不是默认的。我们用一个例子来说明这一点,我发现一开始我觉得很有趣的行为。代码如下: #include <stdio.h> #include <signal.h> #define INPUTLEN 100 main(int ac, char *av[]) {

上周我们有一次讲座,内容涉及操作系统(在本例中为Linux,在本例中为我们的学校服务器使用SUSE Linux 11)如何处理中断。值得注意的是,对于大多数信号,您可以捕获中断并定义自己的信号处理程序来运行,而不是默认的。我们用一个例子来说明这一点,我发现一开始我觉得很有趣的行为。代码如下:

#include <stdio.h>
#include <signal.h>

#define INPUTLEN 100

main(int ac, char *av[])

{
  void inthandler (int);
  void quithandler (int);
  char input[INPUTLEN];
  int nchars;

  signal(SIGINT, inthandler);
  signal(SIGQUIT, quithandler);

  do {
    printf("\nType a message\n");
    nchars = read(0, input, (INPUTLEN - 1));
    if ( nchars == -1)
      perror("read returned an error");
    else {
      input[nchars] = '\0';
      printf("You typed: %s", input);
    }
  }
  while(strncmp(input, "quit" , 4) != 0); 
}

void inthandler(int s)
{
  printf(" Received Signal %d ....waiting\n", s);
  int i = 0;
  for(int i; i<3; ++i){
    sleep(1);
    printf("inth=%d\n",i);
  }
  printf(" Leaving inthandler \n");
}

void quithandler(int s)
{
  printf(" Received Signal %d ....waiting\n", s);
  for(int i; i<7; ++i){
    sleep(1);
    printf("quith=%d\n",i);
  }  printf(" Leaving quithandler \n");
}
换言之,它似乎是这样处理的:

  • 接收第一个^C信号
  • 接收^ \信号,“延迟”inthandler并进入quithandler
  • 接收下一个^C信号,但由于我们已经“嵌套”在inthandler中,请将其放在inthandler“队列”的后面
  • 接收quithandler,放在quithandler队列的后面
  • 执行quithandler,直到队列为空。忽略第三个quithandler,因为它似乎只有队列深度2
  • 离开quithandler,执行剩下的2个IntHandler。忽略最后一个inthandler,因为队列深度为2
  • 我向我的教授展示了这种行为,他似乎同意“嵌套2队列深度”的行为是正在发生的,但我们不能100%确定原因(他有硬件背景,刚刚开始教这门课)。我想发布到SO,看看是否有人可以解释Linux为什么/如何处理这些信号,因为我们并不太期待一些行为,例如嵌套

    我认为我编写的测试用例应该足以说明发生了什么,但下面是一组附加测试用例的屏幕截图:

    我想把附加的测试用例作为一个链接,因为它们都是大屏幕截图


    谢谢大家!

    我在手册页
    信号(7)
    中发现了这一点,它似乎是相关的:

    实时信号以有保证的顺序发送。倍数 相同类型的实时信号按订单交付 他们被派去了。如果不同的实时信号被发送到 过程中,从编号最低的开始交付 信号。(即,编号较低的信号具有最高优先级。) 对比度,如果一个进程有多个标准信号等待处理, 未指定交付顺序。

    查看
    sigprocmask
    sigpunding
    文档,以及
    signal(7)
    ,可以增强您对未决信号保证的理解

    要从弱的“未指定”保证转移到您的OpenSUSE版本上实际发生的情况,您可能需要检查内核中的信号传递代码。

    规则(对于非实时信号,例如您正在使用的
    SIGQUIT
    SIGINT
    )是:

  • 默认情况下,信号在进入处理程序时被屏蔽,在处理程序退出时被解除屏蔽
  • 如果在屏蔽信号时引发该信号,则该信号处于挂起状态,如果/当该信号被解除屏蔽时,该信号将被传递
  • 挂起状态为二进制-信号为挂起或未挂起。如果一个信号在屏蔽时被多次激发,那么在解除屏蔽时它仍然只会被传递一次

    因此,在您的示例中发生的是:

  • SIGINT
    被引发,并且
    inthandler()
    信号处理程序开始执行,
    SIGINT
    被屏蔽
  • SIGQUIT
    被触发,并且
    quithandler()
    信号处理程序开始执行(中断
    inthandler()
    ),同时
    SIGQUIT
    被屏蔽
  • 将引发
    SIGINT
    ,将
    SIGINT
    添加到挂起信号集(因为它被屏蔽)
  • 将引发
    SIGQUIT
    ,将
    SIGQUIT
    添加到挂起信号集(因为它被屏蔽)
  • SIGQUIT
    已引发,但由于
    SIGQUIT
    已挂起,因此不会发生任何事情
  • SIGINT
    已引发,但由于
    SIGINT
    已挂起,因此不会发生任何事情
  • quithandler()
    完成执行,并且
    SIGQUIT
    被解除屏蔽。由于
    SIGQUIT
    处于挂起状态,因此它随后被传递,并且
    quithandler()
    再次开始执行(再次屏蔽
    SIGQUIT
  • quithandler()
    第二次完成执行,并且
    SIGQUIT
    被解除掩码
    SIGQUIT
    未挂起,因此
    inthandler()
    然后继续执行(而
    SIGINT
    仍被屏蔽)
  • inthandler()
    完成执行,并且
    SIGINT
    被解除屏蔽。由于
    SIGINT
    处于挂起状态,因此它随后被传递,并且
    inthandler()
    再次开始执行(再次屏蔽
    SIGINT
  • inthandler()
    完成第二次执行,并且
    SIGINT
    被解除屏蔽。然后,主函数继续执行
  • 在Linux上,您可以通过检查
    /proc//status
    来查看进程的当前屏蔽和挂起信号集。屏蔽信号显示在
    SigBlk:
    bitmask中,挂起信号显示在
    SigPnd:
    bitmask中


    如果使用
    sigaction()
    而不是
    signal()
    安装信号处理程序,则可以指定
    SA_NODEFER
    标志,以请求在信号处理程序执行时不屏蔽信号。您可以在程序中尝试使用一个或两个信号,并尝试预测输出结果。

    为了获得最佳结果,函数原型应该在任何函数之外。您应该显示运行的代码,而不是近似的代码。“quit”处理程序代码打印“inth”,但记录显示打印“quith”的内容。另请参见,与
    sigaction()
    相比,您对
    sigaction()
    的控制有限。查看发布的代码失败
    ^CReceived signal 2 ....waiting
    ^\Received Signal 3 ....waiting
    ^C^\^\^C quith=0
    quith=1
    quith=2
    quith=3
    quith=4
    quith=5
    quith=6
    quith=7
    Leaving quithandler
    Received Signal 3 ....waiting
    quith=1
    quith=2
    quith=3
    quith=4
    quith=5
    quith=6
    quith=7
    Leaving quithandler
    inth=0
    inth=1
    inth=2
    inth=3
    Leaving inthandler
    Received Signal 2 ....waiting
    inth=0
    inth=1
    inth=2
    inth=3
    Leaving inthandler