linux: 可重入函數與不可重入函數


1. 可重入函數與線程安全

摘自 多線程和多進程的區別(小結) http://blog.csdn.net/hairetz/article/details/4281931

要確保函數線程安全,主要需要考慮的是線程之間的共享變量。

屬於同一進程的不同線程會共享進程內存空間中的全局區和堆,而私有的線程空間則主要包括棧和寄存器。

因此,對於同一進程的不同線程來說,每個線程的局部變量都是私有的,而全局變量、局部靜態變量、分配於堆的變量都是共享的。在對這些共享變量進行訪問時,如果要保證線程安全,則必須通過加鎖的方式。 

 

要確保函數可重入,需滿足以下幾個條件:

1、不在函數內部使用靜態或全局數據 
2、不返回靜態或全局數據,所有數據都由函數的調用者提供。 
3、使用本地數據,或者通過制作全局數據的本地拷貝來保護全局數據。
4、不調用不可重入函數。

 

可重入與線程安全並不等同,一般說來,可重入的函數一定是線程安全的,但反過來不一定成立。線程安全函數包括了可重入的函數,但不全是可重入函數;

比如:strtok函數是既不可重入的,也不是線程安全的;加鎖的strtok不是可重入的,但線程安全;而strtok_r既是可重入的,也是線程安全的。

如果我們的線程函數不是線程安全的,那在多線程調用的情況下,可能導致的后果是顯而易見的——共享變量的值由於不同線程的訪問,可能發生不可預料的變化,進而導致程序的錯誤,甚至崩潰。

 

2. 可重入和不可重入 http://www.cnblogs.com/sky-heaven/p/5341759.html

可重入函數列表:

_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()。

 

滿足下面條件之一的多數是不可重入函數:
(1)使用了靜態數據結構;
(2)調用了malloc或free;
(3)調用了標准I/O函數;標准io庫很多實現都以不可重入的方式使用全局數據結構。
(4)進行了浮點運算.許多的處理器/編譯器中,浮點一般都是不可重入的 (浮點運算大多使用協處理器或者軟件模擬來實現。

 

3個問題:

為什么需要可重入?

哪些地方需要可重入?

那些地方不需要可重入?

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM