Linux--信号时序竞态

来源:互联网 发布:淘宝联盟api如何使用 编辑:程序博客网 时间:2024/05/21 14:49

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;}


0 0
原创粉丝点击