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;}
新聞熱點
疑難解答