The alarm function allows us to set a timer that will expire(中止) at a specified time in the future.
When the timer expires, the SIGALRM signal is generated. If we ignore or don’t catch this signal, its default action is to terminate the process.
#include <unistd.h>
unsigned int alarm(unsigned int seconds);
//Return:0 or number of seconds until previously set alarm
alarm参数
调用alarm
会使得之前调用alarm
的参数 seconds 返回。如果seconds
参数为0,之前的alarm clock
取消。
The pause function suspends the calling process until a signal is caught.
#include <unistd.h>
int pause(void);
//Returns: −1 with errno set to EINTR
Example
1. 利用stejmp和longjmp解决sleep的race condition问题
static jmp_buf env_alrm;
static void sig_alrm(int signo)
{
longjmp(env_alrm, 1);
}
unsigned int sleep2(unsigned int seconds)
{
if (signal(SIGALRM, sig_alrm) == SIG_ERR)
return(seconds);
if (setjmp(env_alrm) == 0) {
alarm(seconds); /* start the timer */
pause(); /* next caught signal wakes us up */
}
return(alarm(0)); /* turn off timer, return unslept time */
}
解决了在调用pause之前就已经触发了signal handler
,而导致pause永久阻塞下去的问题。
潜在问题
- 使用
setjmp
和longjmp
会导致sleep
中止掉其他signal handlers
- 调用者已经有
alarm set
,之前的alarm
会被清除 - 我们该变了SIGALRM的disposition(序列)
2. reading one line from standard input and writing it to standard output.
我们有时在read
会需要当超过一定时间直接返回的功能。
static void sig_alrm(int);
int main(void)
{
int n;
char line[MAXLINE];
if (signal(SIGALRM, sig_alrm) == SIG_ERR)
err_sys("signal(SIGALRM) error");
alarm(10);
if ((n = read(STDIN_FILENO, line, MAXLINE)) < 0)
err_sys("read error");
alarm(0);
write(STDOUT_FILENO, line, n);
exit(0);
}
static void sig_alrm(int signo)
{
/* nothing to do, just return to interrupt the read */
}
问题如下:
- alarm和read可能会出现竞争导致,read一直阻塞
- 如果read能自动重启,定时将毫无意义