1、结论:可重入函数必然是线程安全函数异步信号安全函数线程安全函数不一定是可重入函数
例如:strtok是既不可重入的,也不是线程安全的;加锁的strtok不是可重入的,但线程安全。

2、不可重入导致死锁的案例
① 假设函数func()在执行过程中需要访问某个共享资源,因此为了实现线程安全,在使用该资源前加锁,在不需要资源解锁。
② 假设该函数在某次执行过程中,在已经获得资源锁之后,突然有异步信号发生,程序的执行权转交给对应的信号处理函数;
③ 再假设在该信号处理函数中也需要调用函数 func(),那么func()在这次执行中仍会在访问共享资源前试图获得资源锁,然而前一个func()实例已然获得该锁,因此信号处理函数阻塞;另一方面,信号处理函数结束前被信号中断的线程是无法恢复执行的,当然也没有释放资源的机会 ⇒ ⇒ ⇒ 这样就出现了线程和信号处理函数之间的死锁局面。

因此,func()尽管通过加锁的方式能保证线程安全,但是由于函数体对共享资源的访问,因此是非可重入。

我们知道,当捕捉到信号时,不论进程的主控制流程当前执行到哪儿,都会先跳到信号处理函数中执行,从信号处理函数返回后再继续执行主控制流程。信号处理函数是一个单独的控制流程,因为它和主控制流程是异步的,二者不存在调用和被调用的关系,并且使用不同的堆栈空间。

3、不可重入导致插入链表错乱的案例
main函数调用insert函数向一个链表head中插入节点node1,插入操作分为两步,刚做完第一步的时候,因为硬件中断使进程切换到内核,再次回用户态之前检查到有信号待处理,于是切换到sighandler函数,sighandler也调用insert函数向同一个链表head中插入节点node2,插入操作的两步都做完之后从sighandler返回内核态,再次回到用户态就从main函数调用的insert函数中继续往下执行,先前做第一步之后被打断,现在继续做完第二步。结果是,main函数和sighandler先后向链表中插入两个节点,而最后只有一个节点真正插入链表中了。

像上例这样,insert函数被不同的控制流程调用,有可能在第一次调用还没返回时就再次进入该函数,这称为重入,insert函数访问一个全局链表,有可能因为重入而造成错乱,像这样的函数称为不可重入函数,反之,如果一个函数只访问自己的局部变量或参数,则称为可重入(Reentrant)函数。

4、不可重入函数的原因在于:
<1> 已知它们使用静态数据结构
<2> 它们调用mallocfree.
因为malloc通常会为所分配的存储区维护一个链接表,而插入执行信号处理函数的时候,进程可能正在修改此链接表。
<3> 它们是标准IO函数.
因为标准IO库的很多实现都使用了全局数据结构

5、导致insert混乱的原因:非原子操作
在上面的图示例子中,main和sighandler都调用insert函数则有可能出现链表的错乱,其根本原因在于,对全局链表的插入操作要分两步完成,不是一个原子操作(假如这两步操作必定会一起做完,中间不可能被打断,就不会出现错乱了)

==解释什么是原子操作?==关于原子操作最原始的说法是一条汇编指令能够完成(对于多线程程序来说原子操作可以指加锁后的几个步骤集合),即使是一条C语句也不一定是一个原子操作,比如 a = 5; 如果a是32位的int变量,在32位机上赋值是原子操作(需要4字节对齐),在16位机上就不是(注:一个字节的读写如bool类型,都是原子性的)。

linux中可重入函数、不可重入函数相关推荐

  1. Linux 中 dlopen、dlsym、dlclose、dlerror函数

    编译时候要加入 -ldl (指定dl库) dlopen 基本定义 功能:打开一个动态链接库  [喝小酒的网摘]http://blog.const.net.cn/a/17154.htm 包含头文件:  ...

  2. 默认标准错误文件linux,Linux中标准输出和标准错误的重导向

    若是一个命令须要长时间在服务器上运行,那么不少时候会用到nohup命令,这时即使远程登陆ssh中断了与服务器的联系,那么在服务器上运行的命令也不会所以而被迫中止.shell 一般状况下,nohup与& ...

  3. Linux中多线程使用信号量(信号灯),和sem_wait()函数使用

    文章目录 编程环境: 信号量(信号灯): 使用步骤: "生产者-消费者"例子: 理论模型: 代码分析: 代码实现: 运行结果: Mac 下对 sem_init()/sem_dest ...

  4. linux怎么重命名多个文件,在Linux中如何一次重命名多个文件详解

    前言 在日常工作中,我们经常需要对一批文件进行重命名操作,例如将所有的jpg文件改成bnp,将名字中的1改成one,等等. 你可能已经知道,我们使用 mv 命令在类 Unix 操作系统中重命名或者移动 ...

  5. linux重命名得通配符,在Linux中如何一次重命名多个文件详解

    前言 在日常工作中,我们经常需要对一批文件进行重命名操作,例如将所有的jpg文件改成bnp,将名字中的1改成one,等等. 你可能已经知道,我们使用 mv 命令在类 Unix 操作系统中重命名或者移动 ...

  6. Linux中glob()、globfree()、getcwd()函数

    Linux中glob()与globfree()函数 文章目录 一.glob()函数 二.globfree()函数 三.getcwd()函数: 四.代码演示 总结 一.glob()函数 glob()函数 ...

  7. linux中副规则_Linux中的命名规范

    注意: 1.除了/(根目录)以外,所有的字符都合法 2.有些字符最好不用,如空格符.制表符.退格符和字符@#¥()- 等. 3.避免使用 ? 作为普通文件名的第一个字符. 4.大小写敏感. 变量命名规 ...

  8. Linux中的可重入函数和不可重入函数

    可重入函数 可重入函数(即可以被中断的函数)可以被一个以上的任务调用,而不担心数据破坏.可重入函数在任何时候都可以被中断,而一段时间之后又可以恢复运行,而相应的数据不会破坏或者丢失. 可重入函数使用的 ...

  9. 【Linux系统编程】可重入和不可重入函数

    00. 目录 文章目录 00. 目录 01. 不可重入函数 02. 可重入函数 03. 判断条件 04. Linux常用可重入函数 05. 附录 01. 不可重入函数 在实时系统的设计中,经常会出现多 ...

最新文章

  1. Xamarin Essentials教程振动Vibration
  2. RunTime技术总结
  3. Shoppica OpenCart 商城自适应主题模板 ABC-0002
  4. 实验一  简单词法分析程序设计
  5. sublime text3支持Vue语法高亮显示步骤(转)
  6. 经典算法题每日演练——第九题 优先队列
  7. 多路归并排序_字节跳动面试:5 亿整数的大文件,如何排序 ?
  8. 「2019冬令营提高组」不同的缩写
  9. Voxengo音频插件合集:Voxengo Total Bundle for Mac
  10. 又一起“删库”跑路:链家程序员怒删公司 9TB 数据,被判 7 年!网友:真惨~...
  11. tomcat 日志切割
  12. 简单数论入门和基础数学知识(未完)
  13. MK802与外部硬件设备的通讯
  14. 17 款程序员神级 Chrome 插件,爱了爱了!
  15. 使用Jwt验证登录demo
  16. android设备操作(十一)
  17. 一个好用的vscode文件图标美化插件
  18. Module 的语法
  19. 远程访问家中路由器,实现web、ssh、aria2、ftp功能
  20. 山顶应试流V1.0——中国应试教育备考方法

热门文章

  1. 房产管理系统是怎样实现以图管房、以图分房的?
  2. 【洞见研报】无糖食品行业研究报告——最炫“零糖”风,解码无糖食品纵横之路
  3. LaTex插入图片以及图片出现一串图片路径文字解决方法
  4. Latex插入图片报错,解决方案亲测有效!
  5. Unity Editor Extensions – Inspectors私人定制
  6. 小福利,带你快速了解数据分析之一元线性回归模型和多元线性回归模型
  7. Linux: 回到根目录cd /
  8. 决策边界绘制和plt.contourf函数讲解
  9. 每日一诗词 —— 假如你不够快乐
  10. 斗鱼主播陈一发彻底“凉”了:直播间被彻底取消