多執行緒與fork

2021-06-17 19:45:08 字數 1505 閱讀 6537

多執行緒程式裡盡量不使用fork

在多執行緒程式裡,在」自身以外的執行緒存在的狀態」下一使用fork的話,就可能引起各種各樣的問題.比較典型的例子就是,fork出來的子程序可能會死鎖.請不要,在不能把握問題的原委的情況下就在多執行緒程式裡fork子程序,

能引起什麼問題呢?

那看看例項吧.一執行下面的**,在子程序的執行開始處呼叫doit()時,發生死鎖的機率會很高.

void* doit(void*) ; nanosleep(&ts, 0); // 10秒

// 睡10秒

pthread_mutex_unlock(&mutex);

return 0;

}int main(void)

pthread_join(t, 0);

// 等待子執行緒結束

}

以下是說明死鎖的理由:

一般的,fork做如下事情

1. 父程序的記憶體資料會原封不動的拷貝到子程序中

2. 子程序在單執行緒狀態下被生成

在記憶體區域裡,

靜態變數mutex的記憶體會被拷貝到子程序裡

.而且,

父程序裡即使存在多個執行緒

,但它們也不會被繼承到子程序裡

. fork的這兩個特徵就是造成死鎖的原因.

譯者注: 死鎖原因的詳細解釋 ---

1. 執行緒裡的doit()先執行.

2. doit執行的時候會給互斥體變數mutex加鎖.

3. mutex變數的內容會原樣拷貝到fork出來的子程序中

(在此之前,mutex變數的內容已經被執行緒改寫成鎖定狀態

).4.

子程序再次呼叫doit的時候,在鎖定互斥體mutex的時候會發現它已經被加鎖,所以就一直等待,直到擁有該互斥體的程序釋放它(實際上沒有人擁有這個mutex鎖

).5.

執行緒的doit執行完成之前會把自己的mutex釋放,但這是的mutex和子程序裡的mutex已經是兩份記憶體.

所以即使釋放了mutex鎖也不會對子程序裡的mutex造成什麼影響.

例如,請試著考慮下面那樣的執行流程,就明白為什麼在上面多執行緒程式裡不經意地使用fork就造成死鎖了*3.

1.    在fork前的父程序中,啟動了執行緒1和2

2.    執行緒1呼叫doit函式

3.    doit函式鎖定自己的mutex

4.    執行緒1執行nanosleep函式睡10秒

5.    在這兒程式處理切換到執行緒2

6.    執行緒2呼叫fork函式

7.    生成子程序

8.    這時,子程序的doit函式用的mutex處於」鎖定狀態」,而且,解除鎖定的執行緒在子程序裡不存在

9.    子程序的處理開始

10.   子程序呼叫doit函式

11.   子程序再次鎖定已經是被鎖定狀態的mutex,然後就造成死鎖

12 9 執行緒與fork

當乙個執行緒呼叫函式fork的時候,整個程序位址空間會被拷貝到子程序中,在8.3節中有提到copy on write.子程序是乙個與父程序完全不同的程序,但是如果父程序和子程序都沒有對記憶體內容進行修改,那麼該記憶體頁就可以在父程序與子程序之間進行共享。通過繼承父程序的整個位址空間,子程序也會繼承父...

多執行緒中使用fork 導致分頁

最近和同事一起處理了乙個 fuse 的大bug 首先看堆疊 core was generated by sf cluster bin pmxcfs program terminated with signal sigabrt,aborted.0 0x00007f2debdcc475 in raise...

linux下多執行緒中的fork介紹

目錄 回想一下 當乙個程式只有主線程的時候呼叫fork,此時fowww.cppcns.comrk會建立出的子程序也會只有一條執行緒 那要是把fork放入多執行緒的程式中呢?我們來試驗下 include include include void pthread fun void arg int mai...