连接:https://baike.baidu.com/item/%E5%8F%AF%E9%87%8D%E5%85%A5%E5%87%BD%E6%95%B0/4521100?fr=aladdinhtml
http://www.gnu.org/software/libc/manual/html_node/POSIX-Safety-Concepts.html#POSIX-Safety-Conceptsnode
在 实时系统的设计中,常常会出现多个任务调用同一个函数的状况。若是这个函数不幸被设计成为不可重入的函数的话,那么不一样任务调用这个函数时可能修改其余任 务调用这个函数的数据,从而致使不可预料的后果。那么什么是可重入函数呢?所谓可重入是指一个能够被多个任务调用的过程,任务在调用时没必要担忧数据是否会 出错。不可重入函数在实时系统设计中被视为不安全函数。安全
知足下列条件的函数多数是不可重入的:数据结构
(1)函数体内使用了静态的数据结构;多线程
(2)函数体内调用了malloc()或者free()函数(malloc内部维护了全局的链表用来管理分配的内存,这就是状态信息,free也同样),并且malloc函数虽然自己是线程安全的,但系统调用时存在全局的heap lock(堆内存锁(全局锁),保证堆内存分配时的一致连续性),信号句柄中使用malloc函数时,有可能会发生在主程序调用malloc时,但还未结束,heap lock还未释放,被信号所中断,再次调用malloc函数,就会出现同一线程对heap lock连续两次锁,即会出现死锁 deadlock。);函数
(3)函数体内调用了标准I/O函数ui
(4)进行了浮点运算.许多的处理器/编译器中,浮点通常都是不可重入的 (浮点运算大多使用协处理器或者软件模拟来实现。spa
把一个不可重入函数变成可重入的惟一方法是用可重入规则来重写他。其实很简单,只要遵照了几条很容易理解的规则,那么写出来的函数就是可重入的。 操作系统
(1)不要使用全局变量。由于别的代码极可能覆盖这些变量值。线程
(2)在和硬件发生交互的时候,切记执行相似disinterrupt()之类的操做,就是关闭硬件中断。完成交互记得打开中断,在有些系列上,这叫作“进入/退出核心”或者用OS_ENTER_KERNAL/OS_EXIT_KERNAL来描述。//这是临界区保护
(3)不能调用任何不可重入的函数。
(4)谨慎使用堆栈。最好先在使用前先OS_ENTER_KERNAL。
可重入函数列表:
_exit()、 access()、alarm()、cfgetispeed()、cfgetospeed()、cfsetispeed()、cfsetospeed ()、chdir()、chmod()、chown()、close()、creat()、dup()、dup2()、execle()、 execve()、fcntl()、fork()、fpathconf ()、fstat()、fsync()、getegid()、 geteuid()、getgid()、getgroups()、getpgrp()、getpid()、getppid()、getuid()、 kill()、link()、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()。