C Linux如何区分定制信号处理程序的优先级?
上周我们有一次讲座,内容涉及操作系统(在本例中为Linux,在本例中为我们的学校服务器使用SUSE Linux 11)如何处理中断。值得注意的是,对于大多数信号,您可以捕获中断并定义自己的信号处理程序来运行,而不是默认的。我们用一个例子来说明这一点,我发现一开始我觉得很有趣的行为。代码如下: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[]) {
#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");
}
换言之,它似乎是这样处理的:
谢谢大家! 我在手册页
信号(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
被解除屏蔽。然后,主函数继续执行/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