【Linux系统编程】可重入和不可重入函数
00. 目录
文章目录
- 00. 目录
- 01. 不可重入函数
- 02. 可重入函数
- 03. 判断条件
- 04. Linux常用可重入函数
- 05. 附录
01. 不可重入函数
在实时系统的设计中,经常会出现多个任务调用同一个函数的情况。如果有一个函数不幸被设计成为这样:那么不同任务调用这个函数时可能修改其他任务调用这个函数的数据,从而导致不可预料的后果。这样的函数是不安全的函数,也叫不可重入函数。
02. 可重入函数
肯定有一个安全的函数,这个安全的函数又叫可重入函数。那么什么是可重入函数呢?所谓可重入是指一个可以被多个任务调用的过程,任务在调用时不必担心数据是否会出错。
一个可重入的函数简单来说就是可以被中断的函数,也就是说,可以在这个函数执行的任何时刻中断它,转入OS调度下去执行另外一段代码,而返回控制时不会出现什么错误;而不可重入的函数由于使用了一些系统资源,比如全局变量区,中断向量表等,所以它如果被中断的话,可能会出现问题,这类函数是不能运行在多任务环境下的。
也可以这样理解,重入即表示重复进入,首先它意味着这个函数可以被中断,其次意味着它除了使用自己栈上的变量以外不依赖于任何环境(包括 static),这样的函数就是purecode(纯代码)可重入,可以允许有该函数的多个副本在运行,由于它们使用的是分离的栈,所以不会互相干扰。如果确实需要访问全局变量(包括 static),一定要注意实施互斥手段。可重入函数在并行运行环境中非常重要,但是一般要为访问全局变量付出一些性能代价。
编写可重入函数时,若使用全局变量,则应通过关中断、信号量(即P、V操作)等手段对其加以保护。
说明:若对所使用的全局变量不加以保护,则此函数就不具有可重入性,即当多个进程调用此函数时,很有可能使有关全局变量变为不可知状态。
示例:假设 Exam 是 int 型全局变量,函数 Squre_Exam 返回 Exam 平方值。那么如下函数不具有可重入性。
int Exam = 0;
unsigned int example( int para )
{ unsigned int temp;Exam = para; // (**)temp = Square_Exam( );return temp;
}
此函数若被多个进程调用的话,其结果可能是未知的,因为当(**)语句刚执行完后,另外一个使用本函数的进程可能正好被激活,那么当新激活的进程执行到此函数时,将使 Exam 赋与另一个不同的 para 值,所以当控制重新回到 “temp = Square_Exam( )” 后,计算出的temp很可能不是预想中的结果。此函数应如下改进。
int Exam = 0;
unsigned int example( int para )
{unsigned int temp;[申请信号量操作] //(1) 加锁Exam = para;temp = Square_Exam( );[释放信号量操作] // 解锁 return temp;
}
申请不到“信号量”,说明另外的进程正处于给 Exam 赋值并计算其平方过程中(即正在使用此信号),本进程必须等待其释放信号后,才可继续执行。若申请到信号,则可继续执行,但其它进程必须等待本进程释放信号量后,才能再使用本信号。
03. 判断条件
保证函数的可重入性的方法:
1)在写函数时候尽量使用局部变量(例如寄存器、堆栈中的变量);
2)对于要使用的全局变量要加以保护(如采取关中断、信号量等互斥方法),这样构成的函数就一定是一个可重入的函数。
满足下列条件的函数多数是不可重入(不安全)的:
1)函数体内使用了静态的数据结构;
2)函数体内调用了malloc() 或者 free() 函数;
3)函数体内调用了标准 I/O 函数。
如何将一个不可重入的函数改写成可重入函数呢?把一个不可重入函数变成可重入的唯一方法是用可重入规则来重写它。其实很简单,只要遵守了几条很容易理解的规则,那么写出来的函数就是可重入的:
1)不要使用全局变量。因为别的代码很可能改变这些变量值。
2)在和硬件发生交互的时候,切记执行类似 disinterrupt() 之类的操作,就是关闭硬件中断。完成交互记得打开中断,在有些系列上,这叫做“进入/ 退出核心”。
3)不能调用其它任何不可重入的函数。
4)谨慎使用堆栈。
04. Linux常用可重入函数
05. 附录
5.1 参考:可重入函数与不可重入函数分析
【Linux系统编程】可重入和不可重入函数相关推荐
- linux系统编程之进程(七):system()函数使用
一,system()理解 功能:system()函数调用"/bin/sh -c command"执行特定的命令,阻塞当前进程直到command命令执行完毕 原型: int syst ...
- linux系统编程之进程(七):system()函数使用【转】
本文转载自:http://www.cnblogs.com/mickole/p/3187974.html 一,system()理解 功能:system()函数调用"/bin/sh -c com ...
- linux系统发送信号的系统调用是,linux系统编程之信号:信号发送函数sigqueue和信号安装函数sigaction...
信号发送函数sigqueue和信号安装函数sigaction sigaction函数用于改变进程接收到特定信号后的行为. sigqueue()是比较新的发送信号系统调用,主要是针对实时信号提出的(当然 ...
- 【Linux】一步一步学Linux系统编程教程汇总(暂时暂停更新......)
00. 目录 文章目录 00. 目录 01. 概述和标准 02. 文件操作 03. 进程概念 04. 进程间通信 05. 多线程 06. 信号 07. 同步与互斥 08. 高级IO 09. 其它 10 ...
- 【Linux系统编程】信号 (上)
00. 目录 文章目录 00. 目录 01. 信号概述 02. 信号编号 03. 信号产生方式 04. kill发送信号 05. pause等待信号 06. 信号处理方式 07. 信号处理函数 08. ...
- linux程序设计百度网盘,linux系统编程视频 百度网盘下载
本帖最后由 雇佣兵333 于 2015-5-19 16:15 编辑 c教程目录: Linux开发快速入门培训 gcc快速入门 Makefile快速入门 GDB快速入门 Linux系统编程之文件篇 01 ...
- linux系统编程之进程(八):守护进程详解及创建,daemon()使用
linux系统编程之进程(八):守护进程详解及创建,daemon()使用 一,守护进程概述 Linux Daemon(守护进程)是运行在后台的一种特殊进程.它独立于控制终端并且周期性地执行某种任务或等 ...
- linux系统编程 传智播客,传智播客王保明Linux培训系列教程全120集
传智播客王保明Linux培训系列教程全120集--更多资源,课程更新在 多智时代 duozhishidai.com 多智时代资源,简介: 第一天: 01-从linux内核角度看linux系统编程 02 ...
- 【Linux系统编程】守护进程、线程
------------->[Linux系统编程/网络编程](学习目录汇总) <-------------- 目录 1.守护进程 1.1 进程组 1.2 会话 1.3 setsid()函数 ...
- Linux系统编程 / 分析开源软件Triggerhappy
哈喽,我是老吴,继续记录我的学习心得 自制力太强导致低效专注 自制力很强的人的成功之道在于,在别人都放弃的情况下仍坚持不懈. 但是这反而会让他们难以关闭专注模式,导致无法进入解决难题所必要的发散模式. ...
最新文章
- SQL SERVER 2014 下IF EXITS 居然引起执行计划变更的案例分享
- 20100506 学习记录:grdview添加新的一行数据
- 使用GridView自带分页的代码
- java 进入catch,JAVA + try catch(FileNotFoundException e)进入catch(Exception e)?
- 10个奇幻的HTML5和Javascript效果
- 深度探索va_start、va_arg、va_end
- 使用HttpSessionBindingListener方法
- 搜狗皮肤php怎么转换,如何给搜狗输入法更换皮肤和输入方式
- boost::graph模块实现Graphviz DOT 语言阅读器
- 很实用的一篇HTTP状态码
- mybatisplus批量插入原理_Word如何批量打印请柬、奖状、桌牌?一键批量制作就这么简单...
- goldendict设置使用vlc或mplayer发音
- 循环char 指针_c 学习笔记 指针
- Python3 安装RobotFramework
- sort降序shell_shell脚本学习指南之文本排序与排重等
- tinyalsa 终极详解
- QQ空间扫码登录协议 Java
- 永磁同步电机最大转矩电流比(PMSM-MTPA)Simulink仿真教程
- CorelDRAW入门教程-用CDR制作漂亮小雨伞
- 自定义对象转换接口实现JDBC的封装
热门文章
- 从人人网抓取高校数据信息,包括,省份 - 高校 - 院系 (提供最终SQL文件下载)...
- 【JAVASCRIPT】无刷新评论
- 08年1月Gartner商务智能平台魔法四分区
- 使用遥控器控制汽车,实现高难度的泊车(发明畅想)
- ASP.NET中的数据绑定:哪个更快? (转)
- sys接口linux编程,网络编程常用接口的内核实现----sys_listen()
- 每日算法C语言1-求某整数
- oracle触发器比较,Oracle使用触发器和mysql中使用触发器的比较
- django定义模型类-14
- 使用TFS+GIT实现分布式项目管理