如何覆盖(重置)SIGUSR1的默认行为?

时间:2012-10-28 07:44:46

标签: c signals

我在信号处理函数中读到有关add signal()函数的信息可以覆盖默认行为:

#include <stdio.h>
#include <signal.h>
#include <unistd.h>
void signalHandler();
int main(void) {
    signal(SIGUSR1, signalHandler);
    sleep(60);
    printf("I wake up");
    return 0;
}
void signalHandler() {
    signal(SIGUSR1, signalHandler);// I add this line to overwrite the default behaviour 
    printf("I received the signal");
}

我用另一个进程触发它

#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
int main(int argc, char *argv[]) {

    kill(5061, SIGUSR1); // 5061 is the receiver pid, kill(argv[1], SIGUSR1) doesn't working, when I get 5061 as parameter
    puts("send the signal ");
    return 0;
}

接收器wake up接收SIGUSR1信号后立即处理sleep。即使接收到来自其他进程的信号,如何使接收器继续kill(5061, SIGUSR1);

BTW为什么kill(argv[1], SIGUSR1) 5061是接收器pid,{{1}}不起作用,当我得到5061作为参数时?

3 个答案:

答案 0 :(得分:5)

sleep(3)手册页:

  

返回值

     

如果请求的时间已经过去,则为零,如果呼叫被信号处理程序中断,则为剩余的秒数。

所以不要只是调用sleep,而是必须检查返回值并调用循环:

int sleep_time = 60;
while ((sleep_time = sleep(sleep_time)) > 0)
    ;

答案 1 :(得分:3)

你的问题(为什么kill(argv[1], SIGUSR1)不起作用)实际上与信号无关,而与基本的C编程无关。请在Linux上使用gcc -Wall -g进行编译(即所有警告和调试信息),并改进代码,直到没有警告为止。

请仔细阅读kill(2)手册页(在Linux上,在{Untntu或Debian上安装manpagesmanpages-dev以及man-db等软件包后,您可以输入{{1在你的计算机上阅读它。请仔细阅读signal(2)signal(7)手册页。多次阅读这些手册页。

然后,了解kill系统调用声明为

man 2 kill

由于int kill(pid_t pid, int sig); 是某种整数类型,因此您需要将pid_t(这是一个字符串,即argv[1])转换为某个整数(并且char*不应该甚至编译没有错误,因为kill(argv[1], SIGUSR1)不是某个整数而是字符串)。所以请使用:

argv[1]

该手册页还说明您应该使用kill((pid_t) atoi(argv[1]), SIGUSR1); 来恢复默认行为,并signal(SIGUSR1, SIG_DFL)忽略该信号。

当然,您应该更好地使用sigaction(2)作为signal(SIGUSR1, SIG_IGN)的手册页告诉您。

最后,请养成阅读手册的习惯,花几个小时阅读好Advanced Linux ProgrammingAdvanced Unix Programming等好书。他们解释的事情比我们在几分钟内解释的要好得多。如果您不熟悉 C编程,请阅读一些好书。

答案 2 :(得分:2)

我之前没有尝试过,但您可以使用sigaction(2)代替并设置SA_RESTART标志,这应该可以使系统调用重新启动。

修改: 实际上这不起作用,根据signal(7)的手册页,并非所有系统调用都可以重启:

  

如果被a打断,sleep(3)函数也永远不会重启   handler,但返回成功:剩余的秒数   睡觉

所以你应该用剩余的时间再次调用sleep函数。