什么是可重入函数

什么叫可重入:

可重入是一个并发下才有的概念。如果说,程序是串行的,自然也就不会有可重入这回事了。因为并发,所以任何个步骤都可能在运行中途被中断,然后跑另一个代码。这样就会出现一种可能,比如说两段代码都操作了一个全局变量,就会造成意想不到的错误。

可重入函数指的是,有多个线程在并发的执行一个函数。这个时候,如果两个函数会操作同一个全局的变量。这就是上面说的场景了。

什么样的函数不可重入:

  1. 函数体内使用了静态的数据结构(全局变量等)。
  2. 函数体内调用了malloc()或者free()函数
  3. 函数体内调用了标准I/O函数。

注意:malloc函数是不能并发使用的。

举个例子:

在网络开发中 经常出现需要从主机名得到ip地址的情况 这时就使用gethostbyname。很不巧的是,gethostbyname返回的是一个指向静态变量的指针,不可重入。 很可能刚要读时值就被其它线程修改。所以 新的posix中增加了另一个可重入域名解析的函数gethostbyname_r。

gethostbyname_r允许传入地址A和一个缓冲区的地址B,它会把主机信息写入到缓冲区中,然后在地址A上写入结构体,结构体中的指针指向缓冲区。这样实现了可重入,只要传入的缓冲区是独立的。

于是,这就成功引起了GHOST漏洞。关于这个漏洞,可参考《GHOST漏洞原理简单分析》。

另一个来自网上的例子:

A. 可重入函数

1 void strcpy(char *lpszDest, char *lpszSrc) {
2 while(*lpszDest++=*lpszSrc++);
3 *dest=0;
4 }

B. 不可重入函数1

1 char cTemp;//全局变量
2 void SwapChar1(char *lpcX, char *lpcY) {
3 cTemp=*lpcX;
4 *lpcX=*lpcY;
5 lpcY=cTemp;//访问了全局变量
6 }

C. 不可重入函数2

1 void SwapChar2(char *lpcX,char *lpcY) {
2 static char cTemp;//静态局部变量
3 cTemp=*lpcX;
4 *lpcX=*lpcY;
5 lpcY=cTemp;//使用了静态局部变量
6 }

 如何编写可重入的函数?

在函数体内不访问那些全局变量,不使用静态局部变量,坚持只使用局部变量,写出的函数就将是可重入的。如果必须访问全局变量,记住利用互斥信号量来保护全局变量。

  1. 不要使用全局变量。因为别的代码很可能覆盖这些变量值。
  2.  在和硬件发生交互的时候,切记执行类似disinterrupt()之类的操作,就是关闭硬件中断。完成交互记得打开中断,在有些系列上,这叫做“进入/退出核心”。
  3. 不能调用其它任何不可重入的函数
  4.  谨慎使用堆栈。最好先在使用前先OS_ENTER_KERNAL。(没用过,不懂)

总结:

其实,可重入函数和通常的并发编程遇到的问题是一样的,只是不那么容易发现。

我觉得并发编程最难的就是线程同步,就是要解决并发时引起的变量不确定性,还要尽可能高效。这就得靠程序员如何设计一个巧妙地数据结构了。

转载请注明:旅途@KryptosX » 什么是可重入函数

时间: 2024-11-19 11:44:00

什么是可重入函数的相关文章

简介Linux中的可重入函数和不可重入函数

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

linux编程基础(六) 可重入函数、sig_atomic_t类型和volatile限定符

一. POSIX 中对可重入和线程安全这两个概念的定义: Reentrant Function:A function whose effect, when called by two or more threads,is guaranteed to be as if the threads each executed the function one after another in an undefined order, even if the actual execution is inte

2信号处理之:信号产生原因,进程处理信号行为,信号集处理函数,PCB的信号集,sigprocmask()和sigpending(),信号捕捉设定,sigaction,C标准库信号处理函数,可重入函数,

 1信号产生原因 2.进程处理信号行为 manpage里信号3中处理方式: SIG_IGN SIG_DFL                                            默认Term动作 a signal handling function 进程处理信号 A默认处理动作 term   中断 core    core(调试的时候产生) gcc –g file.c     ulimit –c 1024     gdb a.out core ign      忽略 stop

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

主要用于多任务环境中,一个可重入的函数简单来说就是可以被中断的函数,也就是说,可以在这个函数执行的任何时刻中断它,转入OS调度下去执行另外一段代码,而返回控制时不会出现什么错误:而不可重入的函数由于使用了一些系统资源,比如全局变量区,中断向量表等,所以它如果被中断的话,可能会出现问题,这类函数是不能运行在多任务环境下的. 也可以这样理解,重入即表示重复进入,首先它意味着这个函数可以被中断,其次意味着它除了使用自己栈上的变量以外不依赖于任何环境(包括static),这样的函数就是purecode(

【Linux】可重入函数和线程安全的区别与联系【转】

转自:http://blog.csdn.net/scenlyf/article/details/52074444 版权声明:本文为博主原创文章,未经博主允许不得转载. *****可重入函数       函数被不同的控制流程调用,有可能在第一次调用还没返回时就再次进入该函数,这称为重入.       当程序运行到某一个函数的时候,可能因为硬件中断或者异常而使得在用户正在执行的代码暂时终端转而进入你内核,这个时候如有一个信号需要被处理,而处理的这个信号的时候又会重新调用刚才中断的函数,如果函数内部有

Linux多线程可重入函数

Reentrant和Thread-safe 在单线程程序中,整个程序都是顺序执行的,一个函数在同一时刻只能被一个函数调用,但在多线程中,由于并发性,一个函数可能同时被多个函数调用,此时这个函数就成了临界资源,很容易造成调用函数处理结果的相互影响,如果一个函数在多线程并发的环境中每次被调用产生的结果是不确定的,我们就说这个函数是"不可重入的"/"线程不安全"的.为了解决这个问题,POSIX多线程库提出了一种机制,用来解决多线程环境中的线程数据私有化问题,这套机制的主要

深入理解可重入与线程安全

在多线程编程和信号处理过程中,经常会遇到可重入(reentrance)与线程安全(thread-safe). 很多人纠结于reentrance和thread-safe两个概念理解纠缠不清.我想救我对reentrance和thread-safe的理解作个总结   一.可重入(reentrance) 首先来看下APUE中,列出的可重入函数:   accept fchmod lseek sendto stat access fchown lstat setgid symlink aio_error f

Qt之可重入与线程安全

简述 本篇文章中,术语"可重入性"和"线程安全"被用来标记类与函数,以表明它们如何被应用在多线程应用程序中. 一个线程安全的函数可以同时被多个线程调用,甚至调用者会使用共享数据也没有问题,因为对共享数据的访问是串行的. 一个可重入函数也可以同时被多个线程调用,但是每个调用者只能使用自己的数据. 因此,一个线程安全的函数总是可重入的,但一个可重入的函数并不一定是线程安全的. 扩展开来,一个可重入的类,指的是它的成员函数可以被多个线程安全地调用,只要每个线程使用这个类的

linux可重入、异步信号安全和线程安全

一 可重入函数 当一个被捕获的信号被一个进程处理时,进程执行的普通的指令序列会被一个信号处理器暂时地中断.它首先执行该信号处理程序中的指令.如果从信号处理程序返回(例如没有调用exit或longjmp),则继续执行在捕获到信号时进程正在执行的正常指令序列(这和当一个硬件中断发生是所发生的事情相似.)但是在信号处理器里,我们并不知道当信号被捕获时进程正在执行哪里的代码. 如果进程正使用malloc在它的堆上分配额外的内存,而此时由于捕捉到信号而插入执行该信号处理程序,其中又调用了malloc,这会