可重入函数

可重入函数(即可以被中断的函数)可以被一个以上的任务调用,而不担心数据破坏。可重入函数在任何时候都可以被中断,而一段时间之后又可以恢复运行,而相应的数据不会破坏或者丢失。
可重入函数使用的变量有两种情况:
1.使用局部变量,变量保存在CPU寄存器中或者堆栈中;
2.使用全局变量,但是这时候要注意保护全局变量(防止任务中断后被其它任务改变变量)。
?
1
2
3
4
5
void strcpy(*dest,*src)
    while(* dest++ = *src ++){;}
    *dest = NUL;

分析:上面的函数用于字符串复制,而参数是存放在堆栈中的,故而改函数可以被多任务调用,而不必担心各个任务调用期间会互相破坏对方的指针。
 
基本上下面的函数都是不可重入的:
    1.函数内使用了静态的数据。
    2.函数内使用了malloc()或者free()函数的。
    3.函数内调用了标准的I/O函数的。
?
1
2
3
4
5
6
7
int temp;
 void swap(int *ex1,int *ex2)
    temp = *ex1; //(1)
    *ex1 = *ex2;
    *ex2 = temp;

分析:该函数中的全局变量temp是的函数变成了一个不可重入的函数,因为在多任务系统中,假如在任务1中调用swap函数,而程序执行到(1)处时被中断,进而执行其它的任务2,而刚好任务2也调用了swap函数,则temp里存的值则会被任务2改变。从而回到任务1被中断处继续执行的时候,temp里存的值已经不再是原来存的temp值了,进而产生了错误。
 
常用的可重入函数的方法有:
1.不要使用全局变量,防止别的代码覆盖这些变量的值。
2.调用这类函数之前先关掉中断,调用完之后马上打开中断。防止函数执行期间被中断进入别的任务执行。
3.使用信号量(互斥条件)。
总之:要保证中断是安全的

不可重入函数

在多任务系统下,中断可能在任务执行的任何时间发生;如果一个函数的执行期间被中断后,到重新恢复到断点进行执行的过程中,函数所依赖的环境没有发生改变,那么这个函数就是可重入的,否则就不可重入。

在中断前后不都要保存和恢复上下文吗,怎么会出现函数所依赖的环境发生改变了呢?

我们知道中断时确实保存一些上下文,但是仅限于返回地址,cpu寄存器等之类的少量上下文,而函数内部使用的诸如全局或静态变量,buffer等并不在保护之列,所以如果这些值在函数被中断期间发生了改变,那么当函数回到断点继续执行时,其结果就不可预料了。

满足下面条件之一的多数是不可重入函数:

(1)使用了静态数据结构;

(2)调用了malloc或free;

(3)调用了标准I/O函数;

(4)进行了浮点运算.

 

malloc/free是不可重入的,它们使用了全局变量来指向空闲区;标准I/O库的很多实现都使用了全局数据结构; 许多的处理器/编译器中,浮点一般都是不可重入的 (浮点运算大多使用协处理器或者软件模拟来实现)。

 

在信号处理程序及多线程编程时,要特别注意。

考虑这种情况:

1) 信号处理程序A内外都调用了同一个不可重入函数B;B在执行期间被信号打断,进入A (A中调用了B),完事之后返回B被中断点继续执行,这时B函数的环境可能改变,其结果就不可预料了。

2) 多线程共享进程内部的资源,如果两个线程A,B调用同一个不可重入函数F,A线程进入F后,线程调度,切换到B,B也执行了F,那么当再次切换到线程A时,其调用F的结果也是不可预料的。

在信号处理程序中即使调用可重入函数也有问题要注意。作为一个通用的规则,当在信号处理程序中调用可重

入函数时,应当在其前保存errno,并在其后恢复errno。(要了解经常被捕捉到的信号是SIGCHLD,其信号处理程序通常要调用一种wait函数,而各种wait函数都能改变errno。)

Linux中的可重入函数和不可重入函数相关推荐

  1. Linux中__init、__devinit等初始化宏解析和入口函数

    一.初始化宏 1.1.定义 在内核里经常可以看到__init, __devinit这样的语句,这都是在init.h中定义的宏,gcc在编译时会将被修饰的 1 2 内容放到这些宏所代表的section, ...

  2. linux中的变量前加__user,linux中的环境变量,别名,变量传递和函数块

    一,概述 变量的定义 变量即在程序运行过程中它的值是允许改变的量 变量是用一串固定的字符来标示不固定的值的一种方法 变量是一种使用方便的占位符,用于引用计算机内存地址,该地址可以存储 Script 运 ...

  3. linux中DIR、dirent、opendir()、readdir()、closedir()函数的使用

    一. 1.DIR 属性:数据类型: 头文件:#include <dirent.h> 用法:定义一个指向文件目录的指针: 举例:DIR *dirpt =null; 2.dirent 属性:数 ...

  4. Linux中的socket编程

    目录 0.前言 1.Linux中socket编程接口详解 1.1.socket函数 1.2.bind函数 为什么addr参数要使用sockaddr_in 结构体,然后再强制转换为 sockaddr 类 ...

  5. linux连接本机mysql数据库,Linux中MySQL连接本机数据库客户端

    Linux中MySQL连接本机数据库客户端 Linux中MySQL连接本机数据库客户端 1.登入mysql数据库 2.找到要修改的位置 // 选定要用的数据库(用show databases;看完再u ...

  6. linux中可重入函数、不可重入函数

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

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

    在实时系统的设计中,经常会出现多个任务调用同一个函数的情况.如果有一个函数不幸被设计成为这样:那么不同任务调用这个函数时可能修改其他任务调用这个函数的数据,从而导致不可预料的后果.这样的函数是不安全的 ...

  8. Linux信号编程实践(二) 信号发送函数和可重入函数

    在早期的UNIX中信号是不可靠的,不可靠在这里指的是:信号可能丢失,一个信号发生了,但进程却可能一直不知道这一点. 现在Linux 在SIGRTMIN实时信号之前的都叫不可靠信号,这里的不可靠主要是不 ...

  9. RTOS中的可重入函数与不可重入函数

    主要体现在实时操作系统(RTOS)中,即多任务环境中,经常会出现多个任务调用同一个函数的情况. 一.不可重入函数 1.概念 不可重入函数,即不能重复进入的函数,不能被中断的函数.在多个任务调用这个函数 ...

最新文章

  1. Android API 中文 (51) —— ZoomButtonsController
  2. python日历下拉框_Python版的农历日历Calendar,功能简单
  3. eclipse mac 下载php文件夹,PHP Pydev Eclipse (linux or mac)
  4. 51nod 1021 石子归并 (动态规划 简单代码)
  5. 【Pytorch神经网络实战案例】04 使用Pytorch实现线性回归
  6. Linux Polkit 中的pkexec 组件存在的本地权限提升漏洞(CVE-2021-4034)修复方法及centos6和centos7的安装包
  7. Bailian3164 奇偶排序【排序】
  8. 我要自学编程,Java和C语言相比哪个好?
  9. RedHat7 安装 MySQL 5.7
  10. 记者调查:害死多条人命的校园贷卷土重来 支付机构金运通牵涉其中
  11. 写bat文件,报系统找不到指定文件的处理方式
  12. Eclipse+Java+Swing实现企业人事管理系统
  13. java根据经纬度获取地址信息
  14. Codeforces Round #548 (Div. 2) 1139 D+2021天梯赛l3-3 解题报告(负二项式分布+莫比乌斯容斥+杜教筛(天梯赛))
  15. 保证只要看一遍,新手也能写出来的超简单五子棋代码
  16. pve万兆网卡驱动_家庭万兆方案性价比之选,10G网速不是梦!战在当下,布局未来!...
  17. (高能预警!)为什么Gram矩阵可以代表图像风格?带你揭开图像风格迁移的神秘面纱!
  18. TensorFlow实现自定义Op
  19. ssm项目——教务系统
  20. OUC暑期培训(深度学习)——第四周学习记录:MobileNetV1,V2,V3

热门文章

  1. fail2ban防止暴力破解
  2. 转: 从微信的故障谈谈服务可用性
  3. hibernate对象管理
  4. [推荐]在线测试你的网速
  5. K8S调度之pod亲和性
  6. oracle存储过程、声明变量、for循环(转)
  7. 第三章 Git使用入门 心得笔记
  8. sublime text3 jshint 安装
  9. MySQL federated 引擎跨服务器使用实例
  10. 虚拟启动光盘-从ISO光盘镜像引导系统