linux中可重入函数、不可重入函数
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> 它们调用malloc
和free
.
因为malloc通常会为所分配的存储区维护一个链接表,而插入执行信号处理函数的时候,进程可能正在修改此链接表。
<3> 它们是标准IO函数
.
因为标准IO库的很多实现都使用了全局数据结构
5、导致insert混乱的原因:非原子操作
在上面的图示例子中,main和sighandler都调用insert函数则有可能出现链表的错乱,其根本原因在于,对全局链表的插入操作要分两步完成,不是一个原子操作(假如这两步操作必定会一起做完,中间不可能被打断,就不会出现错乱了)
。
==解释什么是原子操作?==关于原子操作最原始的说法是一条汇编指令能够完成(对于多线程程序来说原子操作可以指加锁后的几个步骤集合),即使是一条C语句也不一定是一个原子操作,比如 a = 5; 如果a是32位的int变量,在32位机上赋值是原子操作(需要4字节对齐),在16位机上就不是(注:一个字节的读写如bool类型,都是原子性的)。
linux中可重入函数、不可重入函数相关推荐
- Linux 中 dlopen、dlsym、dlclose、dlerror函数
编译时候要加入 -ldl (指定dl库) dlopen 基本定义 功能:打开一个动态链接库 [喝小酒的网摘]http://blog.const.net.cn/a/17154.htm 包含头文件: ...
- 默认标准错误文件linux,Linux中标准输出和标准错误的重导向
若是一个命令须要长时间在服务器上运行,那么不少时候会用到nohup命令,这时即使远程登陆ssh中断了与服务器的联系,那么在服务器上运行的命令也不会所以而被迫中止.shell 一般状况下,nohup与& ...
- Linux中多线程使用信号量(信号灯),和sem_wait()函数使用
文章目录 编程环境: 信号量(信号灯): 使用步骤: "生产者-消费者"例子: 理论模型: 代码分析: 代码实现: 运行结果: Mac 下对 sem_init()/sem_dest ...
- linux怎么重命名多个文件,在Linux中如何一次重命名多个文件详解
前言 在日常工作中,我们经常需要对一批文件进行重命名操作,例如将所有的jpg文件改成bnp,将名字中的1改成one,等等. 你可能已经知道,我们使用 mv 命令在类 Unix 操作系统中重命名或者移动 ...
- linux重命名得通配符,在Linux中如何一次重命名多个文件详解
前言 在日常工作中,我们经常需要对一批文件进行重命名操作,例如将所有的jpg文件改成bnp,将名字中的1改成one,等等. 你可能已经知道,我们使用 mv 命令在类 Unix 操作系统中重命名或者移动 ...
- Linux中glob()、globfree()、getcwd()函数
Linux中glob()与globfree()函数 文章目录 一.glob()函数 二.globfree()函数 三.getcwd()函数: 四.代码演示 总结 一.glob()函数 glob()函数 ...
- linux中副规则_Linux中的命名规范
注意: 1.除了/(根目录)以外,所有的字符都合法 2.有些字符最好不用,如空格符.制表符.退格符和字符@#¥()- 等. 3.避免使用 ? 作为普通文件名的第一个字符. 4.大小写敏感. 变量命名规 ...
- Linux中的可重入函数和不可重入函数
可重入函数 可重入函数(即可以被中断的函数)可以被一个以上的任务调用,而不担心数据破坏.可重入函数在任何时候都可以被中断,而一段时间之后又可以恢复运行,而相应的数据不会破坏或者丢失. 可重入函数使用的 ...
- 【Linux系统编程】可重入和不可重入函数
00. 目录 文章目录 00. 目录 01. 不可重入函数 02. 可重入函数 03. 判断条件 04. Linux常用可重入函数 05. 附录 01. 不可重入函数 在实时系统的设计中,经常会出现多 ...
最新文章
- Xamarin Essentials教程振动Vibration
- RunTime技术总结
- Shoppica OpenCart 商城自适应主题模板 ABC-0002
- 实验一 简单词法分析程序设计
- sublime text3支持Vue语法高亮显示步骤(转)
- 经典算法题每日演练——第九题 优先队列
- 多路归并排序_字节跳动面试:5 亿整数的大文件,如何排序 ?
- 「2019冬令营提高组」不同的缩写
- Voxengo音频插件合集:Voxengo Total Bundle for Mac
- 又一起“删库”跑路:链家程序员怒删公司 9TB 数据,被判 7 年!网友:真惨~...
- tomcat 日志切割
- 简单数论入门和基础数学知识(未完)
- MK802与外部硬件设备的通讯
- 17 款程序员神级 Chrome 插件,爱了爱了!
- 使用Jwt验证登录demo
- android设备操作(十一)
- 一个好用的vscode文件图标美化插件
- Module 的语法
- 远程访问家中路由器,实现web、ssh、aria2、ftp功能
- 山顶应试流V1.0——中国应试教育备考方法
热门文章
- 房产管理系统是怎样实现以图管房、以图分房的?
- 【洞见研报】无糖食品行业研究报告——最炫“零糖”风,解码无糖食品纵横之路
- LaTex插入图片以及图片出现一串图片路径文字解决方法
- Latex插入图片报错,解决方案亲测有效!
- Unity Editor Extensions – Inspectors私人定制
- 小福利,带你快速了解数据分析之一元线性回归模型和多元线性回归模型
- Linux: 回到根目录cd /
- 决策边界绘制和plt.contourf函数讲解
- 每日一诗词 —— 假如你不够快乐
- 斗鱼主播陈一发彻底“凉”了:直播间被彻底取消