0

我读到了信号处理函数中的 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);5061 是接收器 pid kill(argv[1], SIGUSR1),当我将 5061 作为参数时不起作用?

4

3 回答 3

5

sleep(3)手册页:

返回值

如果请求的时间已经过去,则为零,或者如果调用被信号处理程序中断,则剩余的睡眠秒数。

sleep因此,您必须检查返回值并循环调用,而不是仅仅调用:

int sleep_time = 60;
while ((sleep_time = sleep(sleep_time)) > 0)
    ;
于 2012-10-28T07:54:44.747 回答
3

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

请仔细阅读kill(2)手册页(在 Linux 上,安装软件包后manpagesmanpages-devman-dbUbuntu 或 Debian 上,您可以man 2 kill在计算机上键入阅读它)。另请仔细阅读signal(2)signal(7)手册页。多次阅读这些手册页。

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

int kill(pid_t pid, int sig);

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

kill((pid_t) atoi(argv[1]), SIGUSR1);

手册页还说您应该使用它signal(SIGUSR1, SIG_DFL)来恢复默认行为,并signal(SIGUSR1, SIG_IGN)忽略该信号。

当然,您最好使用sigaction(2)的手册页signal(2)告诉您。

最后,请养成阅读手册页的习惯,花几个小时阅读《高级 Linux 编程》和《高级 Unix 编程》等好书。他们对事情的解释比我们在几分钟内解释的要好得多。如果你不熟悉C 编程,也可以阅读一些关于它的好书。

于 2012-10-28T07:52:20.660 回答
2

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

编辑:实际上这行不通,根据信号(7)的手册页,并非所有系统调用都可以重新启动:

如果被处理程序中断, sleep(3) 函数也永远不会重新启动,但会返回成功:休眠的剩余秒数

因此,您应该sleep使用剩余时间再次调用该函数。

于 2012-10-28T07:50:58.447 回答