上海浦东新区做网站,个人可以建设头条网站吗,网站建设教程试题,wordpress中国网站模板时序竞态是指同样的程序#xff0c;多次调用运行的结果不同#xff0c;这是由于争夺系统资源所造成的。比如说我们要使用alarm和pause函数来实现一个sleep的功能#xff0c;那么由于alarm函数的实现过程并不是一个原子操作#xff0c;那么随时可能被中断。比如说alarm了1秒…时序竞态是指同样的程序多次调用运行的结果不同这是由于争夺系统资源所造成的。比如说我们要使用alarm和pause函数来实现一个sleep的功能那么由于alarm函数的实现过程并不是一个原子操作那么随时可能被中断。比如说alarm了1秒在这个过程中进程失去了CPU然后当该进程再次获得CPU的时候可能这个时间已经大于1秒了那么对于alarm来说就已经发出了SIGALRM信号。此时往下继续调用pause函数的话它会一直都收不到alarm发来的信号所以导致进程的永久挂起。为了解决这个问题引用了sigsuspend函数。sigsuspend用于在接收到某个信号之前临时用mask替换进程的信号掩码并暂停进程执行直到收到信号为止。也就是说进程执行到sigsuspend时sigsuspend并不会立刻返回进程处于TASK_INTERRUPTIBLE状态并立刻放弃CPU等待UNBLOCK(mask之外的)信号的唤醒。进程在接收到UNBLOCK(mask之外)信号后调用处理函数然后还原信号集sigsuspend返回进程恢复执行。下面通过使用alarm和sigsuspend函数来实现sleep函数代码中有详细的注释来解释说明#include #include #include #include #include #include void sig_alarm(int num){ // 空函数仅用来捕捉信号}unsigned int mysleep(unsigned int n_seconds){struct sigaction n_sig, o_sig; // 一个用来设定一个用来备份sigset_t nsigmask, osigmask, tmpsigmask; // 用来设定备份替换/*初始化*/n_sig.sa_handler sig_alarm; // 设定信号的捕捉动作n_sig.sa_flags 0;sigemptyset(n_sig.sa_mask);sigaction(SIGALRM, n_sig, o_sig); // 设定SIGALRM的处理行为/*对SIGALRM信号设置阻塞防止在挂起前出现递达态*/sigemptyset(nsigmask);sigaddset(nsigmask, SIGALRM);sigprocmask(SIG_BLOCK, nsigmask, osigmask); // 设置新mask备份旧maskalarm(n_seconds); // 设置n秒的闹钟/*对原有的mask取消SIGALRM的阻塞*/tmpsigmask osigmask;sigdelset(tmpsigmask, SIGALRM);sigsuspend(tmpsigmask); // 挂起等待没有被阻塞的信号sigprocmask(SIG_SETMASK, osigmask, NULL); // 还原masksigaction(SIGALRM, o_sig, NULL); // 还原处理行为unsigned int unsletp alarm(0); // 获取剩余的睡眠时间/*因为如果没有睡眠够n_seconds就收到了一个唤醒信号那么再次调用alarm会返回剩余的时间*/return unsletp;}int main(void){int ans mysleep(5);printf(%d\n, ans);return 0;}本文同步分享在 博客“Ch_zaqdt”(CSDN)。如有侵权请联系 supportoschina.cn 删除。本文参与“OSC源创计划”欢迎正在阅读的你也加入一起分享。