时序竞态是指同样的程序,多次调用运行的结果不同,这是由于争夺系统资源所造成的。比如说我们要使用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,备份旧mask

alarm(n_seconds); // 设置n秒的闹钟

/*对原有的mask取消SIGALRM的阻塞*/

tmpsigmask = osigmask;

sigdelset(&tmpsigmask, SIGALRM);

sigsuspend(&tmpsigmask); // 挂起等待没有被阻塞的信号

sigprocmask(SIG_SETMASK, &osigmask, NULL); // 还原mask

sigaction(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)。

如有侵权,请联系 support@oschina.cn 删除。

本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

linux多线程时序问题,Linux时序竞态问题(sleep函数的实现)相关推荐

  1. Linux系统编程----8(竞态条件,时序竞态,pause函数,如何解决时序竞态)

    竞态条件(时序竞态): pause 函数 调用该函数可以造成进程主动挂起,等待信号唤醒.调用该系统调用的进程将处于阻塞状态(主动放弃 cpu) 直 到有信号递达将其唤醒,等不到一直等 int paus ...

  2. linux多线程编写哲学家,Linux系统编程(三) ------ 多线程编程

    一.线程的创建和调度 1.线程是程序执行的某一条指令流的映像. 为了进一步减少处理机制的空转时间,支持多处理器及减少上下文切换开销,进程在演化中出现了另一个概念--线程.它是进程内独立的一条运行路线, ...

  3. linux多线程编程和linux 2.6下的nptl,Linux多线程编程和Linux 2.6下的NPTL

    这几天由于工作需要,琢磨了一下Linux下的多线程的相关资料.Linux下最常用的多线程支持库为Pthread库,它是glibc库的组成部分.但是关于Pthread的说明文档非常缺乏,特别是对POSI ...

  4. linux多线程_免费Linux下载工具,你还不知道?

    今天小编要跟大家分享的文章是关于Linux运维人员应该知道的免费Linux下载工具.Windows用户在想要使用下载管理器时可以享受很多选择.如Download Accelerator Plus和Re ...

  5. linux 多线程实现倒计时,Linux用脚本实现“时分秒“倒计时功能

    1.怎样实现"时分秒"倒计时 在Linux下,脚本的完成相对于C语言来说稍微随意一点,可以按照字的想法写,只要有逻辑就可以了. 示例: 注意: clean的功能 这个命令将会刷新屏 ...

  6. linux多线程编程和linux 2.6下的nptl,Linux多線程編程和Linux 2.6下的NPTL

    這幾天由於工作需要,琢磨了一下Linux下的多線程的相關資料.Linux下最常用的多線程支持庫為Pthread庫,它是glibc庫的組成部分.但是關於Pthread的說明文檔非常缺乏,特別是對POSI ...

  7. linux 多线程条件变量,linux多线程之条件变量

    假设有共享的资源sum,与之相关联的mutex 是lock_s.假设每个线程对sum的操作很简单的,与sum的状态无关,比如只是sum++.那么只用mutex足够了.程序员只要确保每个线程操作前,取得 ...

  8. linux多线程select定时器,linux使用select实现精肯定时器详解

    转载自:http://www.jb51.net/article/43199.htm数组 本文讲述如何使用select实现超级时钟.使用select函数,咱们能实现微妙级别精度的定时器.同时,selec ...

  9. linux 两个驱动 竞态,第7章 Linux设备驱动中的并发控制之一(并发与竞态)

    本章导读 Linux设备驱动中必须解决的一个问题是多个进程对共享资源的并发访问,并发的访问会导致竞态(竞争状态). Linux提供了多种解决竞态问题的方式,这些方式适合不同的应用场景. 7.1讲解了并 ...

最新文章

  1. Docker Compose 1.18.0 之服务编排详解
  2. 深入理解编译注解(四)常用接口介绍
  3. 【网址收藏】podman安装及使用简单介绍
  4. 8类网线利弊_超6类网线和7类网线有何区别?有何用途?家用电脑,看这
  5. 【Android】关于Android控件EditText的属性InputType的一些经验
  6. 踩坑记(1)——使用slf4j+logback记录日志
  7. ux和ui_阅读10个UI / UX设计系统所获得的经验教训
  8. 面试官 | 如何在 Spring Boot 中进行参数校验?
  9. CVPR2021 Oral|只用静态图,实时渲染出丝滑3D效果
  10. C语言指针概念全面解析
  11. Protocol Buffers数据编码
  12. 94. autoload
  13. linux fastboot 工具,fastboot工具(FastbootCommander)
  14. win10易升_win10上跑Ubuntu不用虚拟机不用双系统!
  15. 单片机之硬件 软件仿真
  16. mysql normsinv,在MySQL中实现NORMSINV函数
  17. Excel中如何使用COLUMN和COLUMNS函数
  18. Windows批处理bat文件
  19. 第六章 (数据库) 第3节 数据库高级
  20. BZOJ3202 [Sdoi2013]项链

热门文章

  1. windows下python 使用CRF++ python接口的配置
  2. Flask框架项目实例:**租房网站(一)
  3. java弹窗点击事件_[Java教程]jQuery的click事件在当前页弹出层窗口(不打开新页面)...
  4. 互联网热门职位薪酬报告
  5. 美团内推:java高级开发(一面+二面+三面),面试58题实拍!
  6. CreateFile
  7. Codeforces Round #462 (Div. 2), problem: (C) A Twisty Movement (求可以转一次区间的不递增子序列元素只有1,2)...
  8. jquery的全选和多选操作
  9. H5 与 IOS的爱恨情仇(兼容问题)
  10. css比较特殊选择器汇总(持续更新)