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能自动重启,定时将毫无意义
本文深入探讨Linux内核中信号处理机制与定时器的应用,包括alarm函数、pause函数、race condition解决方案及信号处理在读取输入时的应用。详细解释了如何通过alarm和pause函数实现定时操作,解决race condition问题,并展示了如何在读取标准输入时设置超时限制。同时,文章还讨论了信号处理可能带来的问题及其解决方案。
8505

被折叠的 条评论
为什么被折叠?



