可重入函数与不可重入函数

可重入函数与不可重入函数

概念
  • 可重入函数reentrant):在任意时刻可以被中断,稍后再继续运行,不会丢失数据,即不用担心数据被其他线程篡改。可重入函数必须满足以下三个条件:
    • 可以在执行的过程中可以被打断;
    • 被打断之后,在该函数一次调用执行完之前,可以再次被调用(或进入,reentered)。
    • 再次调用执行完之后,被打断的上次调用可以继续恢复执行,并正确执行。
  • 不可重入函数non-reentrant):多任务调用某一不可重入函数时,可能修改其他任务调用该函数的数据,从而导致不可预料的后果。即不可重入函数不能由超过一个任务所共享,除非能确保函数的互斥(或者使用信号量,或者在代码的关键部分禁用中断)。满足下面条件之一的都数是不可重入函数:
    • 使用了静态数据结构或者全局变量;
    • 调用了malloc或free;
    • 调用了标准I/O函数;标准io库很多实现都以不可重入的方式使用全局数据结构。
    • 进行了浮点运算.许多的处理器/编译器中,浮点一般都是不可重入的 (浮点运算大多使用协处理器或者软件模拟来实现。
    • 调用printf。( 注:printf引用全局stdout; malloc, free会引用全局的内存分配表。)
如何保证可重入
  1. 不要使用全局变量和static变量。因为别的代码很可能改变这些变量值。
  2. 在写函数时候尽量使用局部变量(例如寄存器、堆栈中的变量);
  3. 对于要使用的全局变量要加以保护(如采取关中断、信号量等互斥方法),这样构成的函数就一定是一个可重入的函数。
  4. 不能调用其它任何不可重入的函数。
  5. 谨慎使用堆栈。
  6. 在和硬件发生交互的时候,切记执行类似 disinterrupt() 之类的操作,就是关闭硬件中断。完成交互记得打开中断,在有些系列上,这叫做“进入/ 退出核心”。
可重入与线程安全
  • 可重入函数与线程安全没有必然联系。即,一个可重入函数不一定是线程安全的,一个线程安全的函数不一定是可重入的。比如printf,是线程安全的,但是却不可重入。
  • 但,不可重入函数一定不是线程安全的。
代码示例
  • 不可重入且线程不安全
    • 使用全局变量,导致线程不安全。
int t; 
void swap(int *x, int *y)
{
    t = *x;
    *x = *y;
 
    // hardware interrupt might invoke isr() here!
    *y = t;
}mianain
 
void main()
{
    int x = 1, y = 2;
    swap(&x, &y);
    return;
}
  • 可重入但线程不安全
    • 在swap函数里,在交换前,对此时刻的t全局变量做一个本地的缓存,在交换结束的时候,始终使用该缓存。这样的话,swap函数在退出的时候,全局变量的之跟进入的时候是一样的。这样,就可以保证该函数是线程可重入的。
    • 在多线程环境下,依然是线程不安全的,因为它无法保证全局变量t的一致性。
int t;
void swap(int *x, int *y)
{
    int s;
 
  	s = t; // save global variable</span>
    t = *x;
    *x = *y;
 
    // hardware interrupt might invoke isr() here!
    *y = t;
	t = s; // restore global variable</span>
}
 
void main()
{
    int x = 1, y = 2;
    swap(&x, &y);
    return;
}
Linux常见可重入函数

在这里插入图片描述

参考

https://blog.csdn.net/acs713/article/details/20034511

May 29, 2020 AM 10:28 @DaYang

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值