我有一些用 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 (sleep(5)
) 时,似乎都没有调用 sig_stop
。但是,当我注释掉 sleep(5)
时,sig_stop
清理工作正常。我对如何捕获 SIGTERM
的理解有问题吗?
如果我不能使用 sleep
函数,是否有更好的方法让程序“休眠”,以便它仅每 x 分钟运行一次循环,或者以最小化CPU 负载?
最佳答案
sleep()
和信号
sleep()
不应阻止信号被捕获和信号处理程序被执行。来自manpage for sleep()
(强调我的):
sleep() causes the calling thread to sleep either until the number of real-time seconds specified in seconds have elapsed or until a signal arrives which is not ignored.
举个例子...
#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()
返回 sleep 剩余的秒数。例如,如果它提前 3 秒被中断,它将返回 3
。如果没有被中断,它将返回0
。
编译为 gcc -o test test.c
并运行。然后从另一个终端运行
pkill -15 test
您将看到类似于以下内容的输出...
Sleeping at time 1532273709
Flag raised. Exiting at time 1532273711. sleep() was interrupted 2 seconds early ...
顺便说一句... sleep(x)
睡了 x
秒 - 而不是分钟。
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()
的原因。
关于捕获 SIGTERM,并 sleep 阻止它工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51464443/