我们已经在本文许多例子里使用了sleep函数,并在10.10节给出两个有缺陷的实现。
- #include <unistd.h>
- unsigned int sleep(unsigned int seconds);
- 返回0或未睡眠的秒数。
这个函数导致调用进程被挂起,直到下面某种情况发生:
1、seconds指定的挂钟时间量已经逝去;
2、进程捕获一个信号而信号处理器返回。
和alarm信号一样,真实的返回可能比所请求的更晚,因为其它系统活动。
在第一种情况,返回值为0。当sleep因为信号被捕获(第二种情况)而更早返回时,返回值是未睡眠的秒数(请求的时间减去真实睡眠的时间)。
尽 管sleep可以用alarm函数实现(10.10节),但是这并不是必需的。如果alarm被使用,在这两个函数之间可能会有交互。POSIX.1标准 没有规定这些交互。例如,如果我们执行一个alarm(10)并在3秒挂钟时间后执行一个sleep(5),会发生什么呢?sleep会在5秒返回(假定 这时没有其它信号被捕获),但是另一个SIGALRM信号会在2秒后产生吗?这些细节取决于实现。
Solaris 9用alarm实现sleep。Solaris sleep手册页说前一个调度好的闹钟被恰当处理。例如,在前一个场景里,在sleep返回前,它将重新调度闹钟,使它在2秒后发生;sleep在这种情 况下返回0。(显然,sleep必须为SIGALRM保存信号处理器的地址并在返回前重置它。)还有,如果我们执行一个alarm(6)而3秒后执行一个 sleep(5),sleep在3秒后返回(此时闹钟到时),而不是5秒后。这里,sleep的返回值是2(未睡眠的秒数)。
另一方面,FreeBSD、Linux、Mac OS X使用另一种技术:延迟由nanosleep提供。这个函数被规定为高精度的延迟,由SUS的实现扩展提供。这个函数允许sleep的实现与信号无关。
为了可移植性,你不应该对sleep的实现作任何假设,但是如果你有sleep调用和任何其它计时函数相混的任何意图,则你必须小心可能的交互。
下面的代码展示了POSIX.1 sleep函数的一个实现。这个函数是10.10节里的一个修改,它可靠地处理信号,避免早先实现的竞争条件。我们仍然不处理任何与之前设置的闹钟之间的交互。(正如我们提到的,这些交互没有定义在POSIX.1里。)
- #include <signal.h>
- static void
- sig_alrm(int signo)
- {
- /* nothing to do, just returning wakes up sigsuspend() */
- }
- unsigned int
- sleep(unsigned int nsecs)
- {
- struct sigaction newact, oldact;
- sigset_t newmask, oldmask, suspmask;
- unsigned int unslept;
- /* set our handler, save previous information */
- newact.sa_handler = sig_alrm;
- sigemptyset(&newact.sa_mask);
- newact.sa_flags = 0;
- sigaction(SIGALRM, &newact, &oldact);
- /* block SIGALRM and save current signal mask */
- sigemptyset(&newmask);
- sigaddset(&newmask, SIGALRM);
- sigprocmask(SIG_BLOCK, &newmask, &oldmask);
- alarm(nsecs);
- suspmask = oldmask;
- sigdelset(&suspmask, SIGALRM); /* make sure SIGALRM isn't blocked */
- sigsuspend(&suspmask); /* wait for any signal to be caught */
- /* some signal has been caught, SIGALRM is now blocked */
- unslept = alarm(0);
- sigaction(SIGALRM, &oldact, NULL); /* reset previous action */
- /* reset signal mask, which unblocks SIGALRM */
- sigprocmask(SIG_SETMASK, &oldmask, NULL);
- return(unslept);
- }
要写这个可靠的实现比早先要花费更多的代码。我们不使用任何形式的非本地分支(之前我们用它来避免alarm和pause之间发生的竞争条件),所以对其它当SIGALRM被处理时可能正执行的信号处理器没有效果。
- DB2+HADR+TSA高可用性测试--D...
- PyQt5系列教程(四)信号和槽...
- 欢迎信号旗xin在ChinaUnix博客...
- lesson2-信号与槽机制
- 定位Linux下定位进程被谁KILL...
- A sample .exrc file for vi e...
- IBM System p5 服务器 HACMP ...
- 游标的特征
- busybox的httpd使用CGI脚本(Bu...
- Solaris PowerTOP 1.0 发布