sleep()
и сигналы
sleep()
не должен препятствовать перехвату сигнала и выполнению обработчика сигнала. Из справочной страницы для 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
секунд, а не минут.
signal()
vs 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()
.
person
David Collins
schedule
22.07.2018