一個函數在被調用執行期間(尚未調用結束),由于某種時序(遞歸或者處理信號捕捉時等情況)又被重復調用,稱之為“重入”。根據函數實現的方法可分為“可重入函數”和“不可重入函數”兩種。看如下程序。
可以看出在進程主控程序的insert函數未執行完時(在執行完p->next=head時,收到一個信號,需要立即去處理信號),馬上內核接著調用了insert函數來將node2節點插入鏈表。預期結果應該是node1與node2兩個節點都插入鏈表中形成一個單鏈表,但由于insert函數中的變量head為全局變量,因此函數的兩次調用都可以對同一個變量修改,其修改的順序不同會造成結果不同,最終導致達不到預期的結果。因此,insert函數是不可重入函數,重入調用,會導致意外結果呈現。究其原因,是該函數內部實現使用了全局變量。
可重入函數是指重入不會產生異常結果的函數,即允許在函數執行期間再次調用該函數。
注意事項:
1.對于可重入函數,函數內部不能含有全局變量和static變量,因為這種變量可以被函數的多次重入調用共同控制,其最終的結果依賴于它們的執行順序;
2.可重入函數的定義中也不能使用malloc和free函數,因為malloc和free函數的底層實現是用全局指針完成的;
3.信號捕捉函數應該設計成可重入函數;
4.信號處理程序可以調用的可重入函數可參閱man 7 signal
5.沒有包含在上述列表中的函數大多是不可重入的,其原因為:使用靜態數據結構;調用了malloc或free;是標準I/O函數。
malloc、free系統調用是不可重入函數,底層實現是用全局指針完成的。strtok是不可重入函數,其內部含有一個static變量;strtok_r為可重入函數,其將strtok函數的static變量變為一個非靜態局部變量,作為該函數的第三個參數。