我在信号处理函数中读到有关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作为参数时?
答案 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上安装manpages
和manpages-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 Programming和Advanced Unix Programming等好书。他们解释的事情比我们在几分钟内解释的要好得多。如果您不熟悉 C编程,请阅读一些好书。
答案 2 :(得分:2)
我之前没有尝试过,但您可以使用sigaction(2)代替并设置SA_RESTART
标志,这应该可以使系统调用重新启动。
修改强>: 实际上这不起作用,根据signal(7)的手册页,并非所有系统调用都可以重启:
如果被a打断,sleep(3)函数也永远不会重启 handler,但返回成功:剩余的秒数 睡觉。
所以你应该用剩余的时间再次调用sleep
函数。