1. 有问题的mysleep函数,主要注释部分的解释
#include <stdio.h>#include <unistd.h>#include <stdlib.h>#include <string.h>#include <signal.h>void sig_handle(int signo){ }unsigned int mysleep(unsigned int nsec){ //int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact); struct sigaction newaction, oldaction; newaction.sa_handler = sig_handle; sigemptyset(&newaction.sa_mask); newaction.sa_flags = 0; if (sigaction(SIGALRM, &newaction, &oldaction) < 0) { PRintf("sigaction error/n"); return -1; } //假如CPU太忙了,nsec之后内核还在处理别的进程的事,当处理完成后,内核执行这个进程的事, //由于这时候已经到时间了,按照内核的处理方式,先检查该进程有没有未处理的信号,结果发现 //存在alarm信号没有处理,从而调用信号处理函数。这时候信号到达不了用户空间了。导致pause //无限制等待 alarm(nsec); pause(); unsigned int leaveSec = alarm(0); sigaction(SIGALRM, &oldaction, NULL); return leaveSec;}int main(int argc, char *argv[]){ while(1) { unsigned int leaveSec = mysleep(2); printf("2 seconds after, leave %u!/n", leaveSec); } return 0;}2. 改进后的mysleep函数,使用信号屏蔽和挂起的原子操作#include <stdio.h>#include <unistd.h>#include <stdlib.h>#include <string.h>#include <signal.h>void sig_handle(int signo){ }unsigned int mysleep(unsigned int nsec){ sigset_t newset, oldset, emptyset; sigemptyset(&newset); sigemptyset(&emptyset); sigaddset(&newset, SIGALRM); if (sigprocmask(SIG_BLOCK, &newset, &oldset) < 0) { printf("sigprocmask error/n"); return -1; } struct sigaction newact, oldact; newact.sa_handler = sig_handle; sigemptyset(&newact.sa_mask); newact.sa_flags = 0; if (sigaction(SIGALRM, &newact, &oldact) < 0) { printf("sigaction error/n"); return -1; } alarm(nsec); sigsuspend(&emptyset); unsigned int nleave = alarm(0); sigaction(SIGALRM, &oldact, NULL); sigprocmask(SIG_SETMASK, &oldset, NULL); return nleave;}int main(int argc, char *argv[]){ while(1) { unsigned int leave = mysleep(1); printf("1s passed, time leave %u/n", leave); } return 0;}
新闻热点
疑难解答