sleep的可靠实现(APUE)
sleep使进程一直挂起,直到满足一下两个条件之一:
1、睡眠时间到时;
2、调用进程捕捉到一个信号,并从该信号处理函数返回;
以下是APUE中实现sleep函数的源码,坑爹的我看了半天才明白,受伤。
1 #include "apue.h"
2 #include <signal.h>
3
4 static void
5 sig_alrm(int signo)
6 {
7
8 }
9
10 unsigned int
11 sleep(unsigned int nsecs)
12 {
13 struct sigaction newact, oldact;
14 sigset_t newmask, oldmask, suspmask;
15 unsigned int unslpt;
16
17 newact.sa_handler = sig_alrm;
18 sigemptyset(&newact.sa_mask);
19 newact.sa_flags = 0;
20
21 sigaction(SIGALRM, &act, &oldact);
22
23 sigemptyset(&newmask);
24 sigaddset(&newmask, SIGALRM);
25
26 if(sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0)
27 err_sys("sigprocmask(SIG_BLOCK)");
28
29 alarm(nsecs);
30
31 suspmask = oldmask;
32 sigdelset(&suspmask, SIGALRM);
33
34 sigsuspend(&suspmask);
35
36 unslept = alrm(0);
37
38 sigaction(SIGALRM, &oldact, NULL);
39
40 sigprocmask(SIG_SETMASK, &oldmask, NULL);
41
42 return unslept;
43 }
函数sig_alrm的作用仅仅是返回到sigsuspend,所以空函数体就行了。整个函数框架,首先阻塞SIGALRM信号,注意是阻塞而不是忽略,这是为了防止当执行其他信号处理函数时,SIGALRM打断执行过程。然后设置SIGALRM信号处理函数,仅仅是空函数体,为了sigsuspend函数的返回,然后开启定时器,调用alarm函数,此时需要保证SIGALRM并没有阻塞,否则的话,整个函数就失去意义,即使时间到了,因为sigsuspend阻塞了SIGALRM信号,是进程一直挂起(当然没有其他信号到来),sigsuspend返回之后,可能是sig_alrm返回(即时间到,前文第一种情况),也可能是进程捕捉到一个信号,并从该信号处理函数返回(前文第二种情况),记下此时的剩余时间。然后取消对SIGALRM的阻塞,重设信号处理函数。
看了很久才知道是这么个意思。失败。