設計思路:先替換原先的處理函數然後通過newmask阻塞sigalrm,從susmask裏除去sigalrm,然後利用sigsuspend函數捕捉sigalrm等未阻塞信號,最後獲得剩餘時間,重置handler和mask。
源代碼:
cat -n 10_29.c
1 #include "apue.h"
2
3 void sig_alarm(int signo)
4 {
5 //do nothing,just wake up sigsuspend;
6 }
7
8 unsigned int sleep(unsigned int seconds)
9 {
10 struct sigaction new_action,old_action;
11 sigset_t newmask,oldmask,susmask;
12 int status;
13
14 //set new handler
15 new_action.sa_handler = sig_alarm;
16 new_action.flags = 0;
17 sigemptyset(&new_action.sa_mask);
18 sigaction(SIGALRM,&new_action,&old_action);
19
20
21 //set new mask
22 sigemptyset(&newmask);
23 sigaddset(&newmask,SIGALRM);
24 sigprocmask(SIG_BLOCK,&newmask,&oldmask);
25
26
27 alarm(seconds);
28 susmask = oldmask;
29
30 //make sure SIGALRM is not blocked
31 sigdelset(&susmask,SIGALRM);
32
33 sigsuspend(&susmask);
34
35 status = alarm(0);
36
37 //reset original handler
38 sigaction(SIGALRM,&old_action,NULL);
39
40 //reset original mask
41 sigprocmask(SIG_SETMASK,&oldmask,NULL);
42
43 return (status);
44 }