Linux C之可重入函数

在这里对Linux C编程中的可重入函数进行部分说明。该笔记是为了以后自己使用的时候查看的,可能会有一些错误。如能指出错误之处,则十分感谢!

可重入函数就是可以在运行期间再次被调用的函数,由于Linux是一个多任务操作系统,在任务执行期间捕捉到信 并对其进行处理时,进程正在执行的指令序列就被信 处理程序临时中断。如果从信 处理程序返回,则继续执行进程断点处的正常指令序列,重新恢复到断点重新执行的过程中,函数所依赖的环境没有发生改变,也就是说这个函数是可重入的,反之就是不可重入的

在进程中断期间,系统会保存和恢复进程的上下文,然而恢复的上下文仅限于返回地址、处理器、寄存器等之类的少量上下文,而函数内部使用的诸如全局或静态变量、buffer等并不在保护之列,所以如果这些值在函数被中断期间发生了改变,那么当函数回到断点继续执行时,其结果就不可预料了。例如一个进程正在执行malloc 分配堆空间,此时程序捕捉到信 发生中断,在执行信 的处理程序中恰好也有一个malloc,这样就会对进程的环境造成破环。因为malloc 通常为它所分配的存储区维护一个链接表,插入执行信 处理函数时,进程可能正在对这张表进行操作,而信 处理函数的调用刚好覆盖了进程的操作,造成错误。

通常来说,满足下面条件之一的大多数是不可重入函数:

  • 使用了静态数据结构。
  • 调用了malloc 函数或free 函数。
  • 调用了标志I/O函数:标准I/O 库的很多实现都以不可重入的方式使用全局数据结构。
  • 进行了浮点运算:在许多的处理器/编译器中,浮点运算一般都是不可重入的,这是因为负电的运算大多使用协处理器或者软件模拟来实现。

在实际应用中,可重入函数可能存在以下两种状况:

  • 信 处理程序A的内外都调用了同一个不可重入函数B;B在执行期间被信 打断,进入A(在A中调用了B),运行完成之后返回B的被中断点继续执行,这时B函数的环境可能改变,其结果就不可预料了。
  • 多线程共享进程内部的资源,如果两个线程A、B调用同一个不可重入函数F,A线程进入F后,进程调度切换到B,B也执行了F,那么当再次切换到线程A时,其调用F的结果是不可预料的。

在信 处理程序中即使调用可重入函数也需要对一些问题进程处理,例如作为一个通用的规则,当在信 处理程序中调用可重入函数时,应当在其前保存errno的值,并在其后恢复这个值,这是因为每个线程只有一个errno变量,信 处理函数可能会修改其值,若要了解经常被捕捉到的信 是SIGCHLD,其信 处理程序通常要调用wait函数,而各种wait函数都能改变errno 的值。

这里给出Linux中的可重入函数列表:

_exit() access() alarm() cfgetispeed() cfgetospeed() cfsetispeed() cfsetospeed(0 chdir()
chmod() chown() close() create() dup() dup2() execle() execve()
fcntl() fork() fpathconf() fstat() fsync() getegid() geteuid() getgid()
getgroups() getpgrp() getpid() getppid() getuid() kill() lseek() mkdir()
mkfifo() open() pathconf() pause() pipe() raise() read() rename()
rmdir() setgid() setpgid() setsid() setuid() sigaction() sigaddset() sigdelset()
sigemptyset() sigfillset() sigismember() signal() sigpending() sigprocmask() sigsuspend() sleep()
stat() sysconf() tcdrain() tcflow() tcflush() tcgetattr() tcgetpgrp() tcsendbreak()
tcsetattr() tcsetpgrp() time() times() umask() uname() unlink() utime()
wait() waitpid() write()          

参考文献:程国钢, 张玉兰. Linux C编程从基础到实践, 清华大学出版 , 2015.

文章知识点与官方知识档案匹配,可进一步学习相关知识CS入门技能树Linux入门初识Linux25111 人正在系统学习中

声明:本站部分文章及图片源自用户投稿,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!

上一篇 2020年9月25日
下一篇 2020年9月25日

相关推荐