我有一些用C编写的代码(在ubuntu 17上工作):
void sig_stop(int sig_num) {
/* Some cleanup that needs to be done */
}
void some_routine(const char *array[], const int length) {
/* Initialization */
signal(SIGTERM, sig_stop);
while (true) {
/* Some function */
/* I have this sleep to minimize the load on the CPU
as I don't need to check the conditions here
all the time. */
sleep(5);
}
}
每当我包括5分钟的睡眠(sleep(5)
)时,似乎都没有呼叫sig_stop
。但是,当我注释掉sleep(5)
时,sig_stop
清理工作正常。我对如何捉住SIGTERM
有什么误解吗?
如果我不能使用sleep
函数,是否有更好的方法“休眠”程序”,使其仅每x分钟运行一次循环或以最小化CPU负载的方式运行?
答案 0 :(得分:3)
sleep()
和信号 sleep()
不应阻止捕获信号和执行信号处理程序。来自manpage for sleep()
(重点是我):
sleep()使调用线程进入睡眠状态,直到经过以秒为单位指定的实时秒数为止,或者直到信号到来而未被忽略。
以下面的示例为例...
#include <signal.h>
#include <stdio.h>
#include <time.h>
#include <unistd.h>
static volatile sig_atomic_t flag = 0;
static void sig_stop(int signum) { flag = 1; }
int main(void) {
int secs_remaining = 0;
signal(SIGTERM, sig_stop);
while (!flag) {
printf("Sleeping at time %d\n", time(NULL));
secs_remaining = sleep(5);
}
printf(
"Flag raised. Exiting at time %d. sleep() was interrupted %d seconds "
"early ...\n",
time(NULL), secs_remaining);
return 0;
}
请注意-在信号中断的情况下-sleep()
返回剩余的睡眠秒数。例如,如果提前3秒钟中断,它将返回3
。如果没有中断,它将返回0
。
编译为gcc -o test test.c
并运行。然后从另一个终端运行
pkill -15 test
您将看到类似于以下内容的输出...
在时间1532273709睡觉
升起的旗帜。在1532273711时间退出。sleep()提前2秒被中断了...
顺便说一下,sleep(x)
睡眠了x
秒(ems)-而不是分钟。
signal()
与sigaction()
由于与signal()
相关的可移植性问题,通常建议改用sigaction()
。 sigaction()
的使用将类似于以下内容。
int main(void) {
struct sigaction sa;
sa.sa_flags = 0;
sigemptyset(&sa.sa_mask);
sa.sa_handler = sig_stop;
if (sigaction(SIGTERM, &sa, NULL) == -1) {
perror("sigaction");
return 1;
}
// Etc.
}
如您所见,sigaction()
的用法比signal()
的用法更为冗长。也许这就是为什么人们有时仍然使用signal()
的原因。