您的位置:首页 > 编程语言

unix 环境高级编程 信号二 可重入函数与不可重入函数

2014-07-03 11:28 267 查看
场景描述:

         在捕捉到信号时,不论进程的主控制流程执行到哪里,在未设计信号阻塞时,都会先跳到信号处理函数中去执行,从信号处理函数返回后再继续执行主控制流程,信号处理函数是一个单独的控制流程,因为它和主控制流程是异步的,两者不存在调用与被调用的关系,并且使用不同的堆栈空间,引入了信号处理函数使得一个进程具有多个控制流程,如果这些控制流程访问相同的全局资源(全局变量,硬件资源),则可能会发生冲突(导致全局变量在信号处理函数中被错误的修改等)

什么叫做重入:

         举个例子来说,在主控制流程中调用了fun()函数,但是在执行fun函数的代码段中间时,被某个信号中断,转去执行信号处理函数,在信号处理函数中又去调用fun()函数,这个叫做重入。也就是说一个函数在不同的控制流程中被同时调用,在一个控制流程中该函数尚未返回时,在另外的控制流程中该函数又被调用。  

 什么是可重入函数:

         一个函数可以被多个任务或者是多个控制流程并发的访问,而不用担心数据错误或者是执行的结果具有可预见性。典型的情况就是函数仅使用局部变量,这个时候在不同的控制流程中调用相同的函数,会在栈空间中维护局部变量而非堆空间中,这样改变的数据也仅仅是当时正在执行的函数的数据,当函数执行完之后栈空间释放,当然不会影响到另外的控制流程中的同一个函数

什么叫做不可重入函数:

         把上面的可重入函数的概念改改就行了。或者是这样理解也行:如果函数在重入条件下使用了未受保护的全局资源,则称为不可重入函数

为使我们自己写的函数成为可重入的,应该:

          不在函数中使用静态变量或者是全局变量 

          不返回全局或者是静态数据,所有的数据都由函数的调用者提供

          使用本地变量,即使使用全局变量,也使用全局变量的本地拷贝

          使用全局数据时,加锁保护

          不调用不可重入函数。

不可重入函数除了上诉相反的条件外,还有:

         函数调用了malloc()或者是free()

         函数调用了标准I/O函数(很多的标准I/O函数都以不可重入的方式使用了全局数据结构,比如隶属于进程的缓冲区)

个人认为其实可重入函数的前几条说的都是一件事,尽量不要使用堆中的数据。因为堆中的数据可以被共享。                                              

         apue中关于不可重入函数的例子举得是getpwnam()这个函数,原因在于这个函数会返回静态的数据结构。这样如果在一个控制流程进程getpwnam的调用的时候被中断执行,在另外的控制流程中调用getpwnam函数,则可能出现问题,因为静态类型的变量会在函数调用中维持其值。

        注意:本人非科班出身,学习apue纯属 个人爱好,希望多加指正不足之处。

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  unix 重入函数