在这里对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进行处理,非常感谢!