我想用c编写一个用于linux的程序来捕获第一个SIGUSR1信号,忽略第二个信号并继续这种行为(catch-ignore)以获取连续的SIGUSR1信号。
我想知道如何在两个处理程序之间保持交替,因为一旦我将处理程序设置为SIG_IGN,信号将被忽略,我将无法检测到它并采取相应的行动。
这是我尝试过的代码:
int tst;
void sigusr1_handler(){
if(tst==0){
signal(SIGUSR1,SIG_IGN);
tst=1;
}
else tst= 0;
}
int main(){
signal(SIGUSR1, sigusr1_handler);
tst=1;
while(1){}
return 0;
}
答案 0 :(得分:1)
你没有。
你可以做的是让你的信号处理者决定是否做某事 - 例如,是否要调用另一个功能。但是,这并不完全可靠,因为像SIGUSR1
这样的standard POSIX signals没有排队。如果在(几乎)同时发送两个或更多信号,则实际仅传送一个。 POSIX实时信号(SIGRTMIN+0
到SIGRTMAX-0
- 从程序员的角度来看,只有数字和语义不同)排队,但即使它们在某些情况下也可以删除。
在所有情况下,请记住信号处理函数只能使用async-signal safe functions。如果您需要能够使用所有功能,则应该阻止所有线程中的信号,并使专用线程使用例如线程接收信号。 sigwaitinfo()
。在这种情况下,你没有信号处理函数,而是一个接收信号的专用线程,因此可以自由使用它想要的任何函数。
如果我们将问题改为"如何在单线程程序中交替处理传递的信号?" ,答案很简单:你使用的是volatile sig_atomic_t
反击。
对于两个选项之间的交替,do_something_odd()
首先:
#include <signal.h>
void my_signal_handler(int signum)
{
static volatile sig_atomic_t count = 0;
switch (++count) {
case 1:
do_something_odd();
break;
default:
count = 0;
do_something_even();
break;
}
}
对于三种情况之间的交替,您可以根据需要添加更多case
语句:
#include <signal.h>
void my_signal_handler(int signum)
{
static volatile sig_atomic_t count = 0;
switch (++count) {
case 2:
do_something_2_of_3();
break;
case 1:
do_something_1_of_3();
break;
default:
count = 0;
do_something_3_of_3()
break;
}
}
以上假设您使用SA_SIGINFO
中没有.sa_flags
的{{3}}安装信号处理程序。
POSIX标准表示您最多可以处理128个案例(因为sig_atomic_t
可以保证能够以这种方式表示0
到127
的值,包括在内。
您可以使用unsigned int
或unsigned long
执行更大的集合,但是SA_NODEFER
中不能有.sa_flags
,并且如果相同的处理程序用于多个信号,.sa_mask
必须具有由同一处理程序集处理的所有其他信号。这可以确保信号处理程序不会被传递给同一个处理程序的另一个信号中断,并允许我们使用非原子计数器变量。
在多线程程序中,必须依赖于编译器提供的原子操作,即遗留sigaction()
内置函数或__sync
内置函数。它们不是GCC特有的;至少英特尔编译器集合和clang也提供它们。对于两个选项之间的交替,可以使用our = __atomic_xor_fetch(&counter, 1, __ATOMIC_SEQ_CST);
或our = __sync_xor_and_fetch(&counter, 1);
来原子地获取和翻转0到1之间的计数器。对于非幂的两个选项,通常使用比较和交换循环。