调查过程中接触到reentrant函数--可重入函数,实在是太久远了,一点都记不起来了。找到了ypxing的帖子,收益很大。原文:
http://bbs.chinaunix.net/viewthread.php?tid=971102
1. reentrant函数
一个函数是reentrant的,如果它可以被安全地递归或并行调用。要想成为reentrant式的函数,该函数不能含有(或使用)静态(或全局)数据(来存储函数调用过程中的状态信息),也不能返回指向静态数据的指针,它只能使用由调用者提供的数据,当然也不能调用non-reentrant 函数.
2. thread-safe函数
Thread safety是多线程编程中的概念,thread safe函数是指那些能够被多个线程同时并发地正确执行的函数.
3. reentrant函数与thread safe函数的区别
reentrant函数与是不是多线程无关,如果是reentrant函数,那么要求即使是同一个进程(或线程)同时多次进入该函数时,该函数仍能够正确的运作.该要求还蕴含着,如果是在多线程环境中,不同的两个线程同时进入该函数时,该函数也能够正确的运作.thread safe函数是与多线程有关的,它只是要求不同的两个线程同时对该函数的调用在逻辑上是正确的.reentrant的要求比thread safe的要求更加严格.reentrant的函数必是thread safe 的,而thread safe的函数未必是reentrant的.
结论:
1. reentrant是对函数相当严格的要求,绝大部分函数都不是reentrant的(APUE上有一个reentrant函数的列表).什么时候我们需要reentrant函数呢?只有一个函数需要在同一个线程中需要进入两次以上,我们才需要reentrant函数.这些情况主要是异步信号处理,递归函数等等.(non-reentrant的递归函数也不一定会出错,出不出错取决于你怎么定义和使用该函数). 大部分时候,我们并不需要函数是reentrant的.
2. 在多线程环境当中,只要求多个线程可以同时调用一个函数时,该函数只要是thread safe的就可以了.我们常见的大部分函数都是thread safe的,不确定的话请查阅相关文档.
3. reentrant和thread safe的本质的区别就在于,reentrant函数要求即使在同一个线程中任意地进入两次以上,也能正确执行.大家常用的malloc函数是一个典型的non-reentrant但是是thread safe函数,这就说明,我们可以方便的在多个线程中同时调用malloc,但是,如果将malloc函数放入信号处理函数中去,这是一件很危险的事情.
4. reentrant函数肯定是thread safe函数,也就是说,non thread safe肯定是non-reentrant函数不能简单的通过加锁,来使得non-reentrant函数变成 reentrant函数.这个链接是说明一些non-reentrant ===> reentrant和non thread safe ===> thread safe转换的
http://www.unet.univie.ac.at/aix/aixprggd/genprogc/writing_reentrant_thread_safe_code.htm
分享到:
相关推荐
例如,在Keil C51中,可以通过添加`reentrant`关键字来声明一个再入函数。 #### 5. Keil C51与再入函数 Keil C51是业界广泛使用的单片机开发工具之一,它支持多种方式来实现再入函数: - **关键字支持**:使用`...
thread-safe函数与reentrant函数密切相关,但更进一步,它保证了即使在多线程环境下并发调用,函数也能正确工作,不引发数据竞争或其他并发问题。实现线程安全的函数通常需要同步原语,如互斥锁或信号量,以保护共享...
- 使用`reentrant`关键字将函数声明为可重入函数,这样可以在函数内部处理更多的参数。 #### 分析调用树正确使用指针函数 Keil C51编译器的一个关键特性在于,它并不会像ANSI C那样将函数参数压入堆栈中,而是将...
#### 一、中断函数的基本格式与特性 C51的中断函数具有特定的格式: ``` void FuncIr(void) interrupt x [using y] ``` - **基本格式说明**: - `void`:表示中断函数没有参数。 - `FuncIr`:中断函数名。 - `...
2. **函数调用与声明**: - **函数声明**:预先声明函数,告诉编译器函数的名称、参数和返回类型,以便在函数定义之前可以调用。 - **函数调用**:调用已定义的函数,提供实际参数列表,逗号分隔每个参数。 3. **...
void myfunc(void) reentrant { ...} ``` 这个定义将产生一个用来存储参数和本地变量的可重入的栈。如果使用了这种方法,那么这个可重入的栈必须在`STARTUP.A51` 中配置。这样会花费更多的RAM并且会减缓可重入函数的...
* 中断函数可以使用`reentrant`关键字声明,以允许函数在主程序和中断中都可调用。 五、递归或可重入函数 在C51单片机中,递归或可重入函数需要特殊处理,以避免函数重入时的数据破坏。可以使用以下两种方法解决...
在多任务系统中,不可重(Reentrant)函数的使用是一项关键且复杂的技术。不可重函数是指在并发环境中,如果一个函数在执行过程中修改了共享数据或者资源,并且没有进行适当的同步控制,那么当多个任务同时调用这个...
在Linux操作系统中,可重入函数(Reentrant Function)和不可重入函数(Non-reentrant Function)是编程中两个非常重要的概念,特别是在多线程和并发编程中。它们的特性决定了它们在处理并发请求时的行为差异,对于...
22. configNUM_THREAD_LOCAL_STORAGE_POINTERS:线程本地存储指针的数量。 除了上述的配置参数,FreeRTOSConfig.h中还包含一些钩子函数相关的定义,例如是否使用空闲钩子函数(configUSE_IDLE_HOOK)和是否使用滴答...
【可重入函数的实现】在Keil C51中,可以通过在函数定义时添加`reentrant`关键字来标记函数为可重入的。这样编译器会在函数调用时使用模拟栈来保存和恢复函数的状态,确保即使在中断或并发调用时,函数的数据也不会...
相比之下,非可重入VI(non-reentrant VI)在同一时间只能被一个任务调用,如果多个任务尝试同时访问,可能会导致数据不一致或者程序挂起。 再来看看"For structure.vi",这是LabVIEW中的循环结构,用于执行一系列...
线程安全分为三种类型:无影响(thread-neutral)、线程安全(thread-safe)和递归安全(reentrant)。 (三) 异步信号安全 异步信号安全是指在信号处理函数中调用某个函数时,不会引起未定义的行为。如果一个函数是...
模式选择通常在项目设置中确定,但也可以在函数定义中指定,前提是与项目设置保持一致。函数的定义应放置在主函数之前,或者在主函数之前进行原型声明并在之后定义。形参定义需要明确每个参数的数据类型。 可重入...
- 在`main()`函数中,首先通过`pthread_create()`函数创建了一个新线程`a_thread`,并将`thread_function`作为新线程执行的函数。 - `thread_function()`函数接收一个字符指针`msg`作为参数,并打印消息。 - 使用...
#ifndef _LIBC_REENTRANT struct sigaction intr, quit; #endif sigset_t omask; sa.sa_handler = SIG_IGN; sa.sa_flags = 0; __sigemptyset(&sa.sa_mask); DO_LOCK(); if (ADD_REF() == 0) { if (__...
- **设置为重入函数**: 使用`reentrant`关键字定义函数,如`void myfunc(void) reentrant { ... }`。这种方式需要在`STARTUP.A51`文件中配置重入堆栈,消耗更多RAM资源,且会降低函数执行速度。 #### 提示无M51文件...
4. **设计为重入函数**:使用`reentrant`关键字声明函数,创建专用堆栈存储函数状态和局部变量,但会增加RAM使用量和降低执行效率。 #### 二、ERROR LXX: MULTIPLE PUBLIC DEFINITIONS ##### 错误解析: 此错误...
重入函数(reentrant)允许被多个进程同时调用,而using m则指定使用哪一组工作寄存器。例如,下面是一个求两数最大值的函数: ```c int max(int x, int y) { int z; z = x > y ? x : y; return z; } ``` 函数...
使用 reentrant 函数需要注意一些限制,例如不能调用不同存储器模式的重入函数。 2. 定义两个同功能的函数,分别在中断和中断外调用。例如,可以定义一个串口打印函数在中断服务中调用,另一个串口打印函数在主循环...