sleep 函数的实现

2014-09-21 19:46:43   最后更新: 2014-09-21 19:46:43   访问数量:808




信号的发送与捕捉中,我们对 sleep 函数进行了实现,但是最终,我们的实现仍有问题,那就是在处理我们的 SIGALRM 信号的过程中,如果开始执行其他的信号,之后回到我们的信号处理函数,然后做函数间跳转,进程行为会不可靠

unsigned int sleep(unsigned int seconds);

 

定义于 unistd.h 中

返回未休眠够的秒数

 

执行 sleep 后进程被挂起,直到满足下列条件之一:

  1. 已经过了 seconds 的秒数
  2. 调用进程捕捉到一个信号并从信号处理程序返回

 

static void sig_alrm(int signo) { /* do nothing*/ } unsigned int sleep(unsigned int nsecs) { struct sigaction newact, oldact; sigset_t newmask, oldmask, suspmask; unsigned int unslept; newact.sa_handler = sig_alrm; sigemtyset(&newact.sa_mask); newact.sa_flags = 0; sigaction(SIGALRM, &newact, &oldact); sigemptyset(&newmask); sigaddset(&newmask, SIGALRM); sigprocmask(SIG_BLOCK, &newmask, &oldmask); alarm(nsecs); suspmask = oldmask; sigdelset(&suspmask, SIGALRM); sigsuspend(&suspmask); unslept = alarm(0); sigaction(SIGALRM, &oldact, NULL); sigprocmask(SIG_SETMASK, &oldmask, NULL); return unslep; }

 

程序中没有任何形式的非局部跳转,因此避免了我们之前的问题

程序中,首先设置了一个空函数作为 SIGALRM 信号的响应函数,然后屏蔽了 SIGALRM,在调用 alarm 产生 SIGALRM 信号后调用 sigsuspend 取消屏蔽并 pause

为什么要这样做呢?考虑如果 alarm 调用后系统立即切换到其他进程,那么如果不进行非局部跳转则无法保证切换回来后是否已经执行过信号响应函数,于是,由于阻塞队列中的信号会在解除阻塞后分别递送一次,所以调用原子的 sigsuspend 之后的等待时间必定是预设的时间,于是进程的工作状态得以保证

 






读书笔记      技术帖      linux      unix      龙潭书斋      apue      unix环境高级编程      signal      信号      sigprocmask      sigaction      sigsuspend      sleep      posix     


京ICP备15018585号