我們先來看乙個程式:
[cpp]view plain
copy
#include
#include
pthread_mutex_t mutex = pthread_mutex_initializer;
void
* th_fn(
void
* arg)
void
ps_fn()
intmain(
void
)
pthread_join(t, 0);
while
(1)
}
執行結果:
# ./a.out
start th_fn.
in th_fn.
start ps_fn.
end th_fn.
ps_fn函式一直都沒有獲取互斥鎖,所以該函式一直都沒有結束。
分析下原因:
1.執行緒裡的th_fn先執行,給互斥變數mutex加鎖。
2.mutex變數的內容會原樣拷貝到fork出來的子程序中,在子程序中mutex的變數的已經被執行緒改寫成鎖定狀態。
3.子程序呼叫ps_fn,在鎖定互斥體mutex的時候會發現它已經被加鎖,所以就一直等待,直到擁有該互斥體的程序釋放它。
但是實際上沒有人擁有這個mutex鎖。
4.執行緒th_fn執行完之前會把自己的mutex釋放,但是這裡的mutex和子程序裡的mutex已經是兩份記憶體,所以即使釋放了
mutex鎖也不會對子程序裡的mutex造成什麼影響。
要規避這個問題的一種方法是子程序從fork返回後馬上呼叫某個exec函式,就可以避免這樣的問題,這種情況下,老的位址
空間被丟棄,所以鎖的狀態無關緊要,但是如果程序需要繼續做處理工作的話,這種方式是行不通的。另一種策略是使用
pthread_atfork函式。
[cpp]view plain
copy
#include
intpthread_atfork(
void
(*prepare)(
void
), void
(*parent)(
void
), void
(*child)(
void
));
//成功則返回0,否則返回錯誤編號
該函式最多可以安裝三個幫助清理的函式。
prepare處理程式由父程序在fork建立子程序前呼叫。
parent處理程式在fork建立子程序以後,但在fork返回之前在父程序環境中呼叫。
child處理程式在fork返回之前在子程序環境中呼叫。
可以多次呼叫pthread_atfork函式從而設定多套fork處理程式。如果不需要使用其中某個處理程式,可以給特定的處理程式
引數傳入空指標,這樣就不會起任何作用作用。使用多個fork處理程式時,處理程式的呼叫順序並不相同。parent和child
處理程式時以它們註冊時的順序進行呼叫的。而prepare處理程式的呼叫順序與它們註冊的順序相反,這樣可以允許多個
模組註冊它們自己的fork處理函式,並且保持鎖的層次。
例如,模組a呼叫模組b中的函式,而且每個模組有自己的一套鎖。如果所的層次是a在b之間,模組b必須在模組a之前設定
fork處理程式,當父程序呼叫fork時,就會執行以下步驟,假設子程序在父程序之前執行。
1.呼叫模組a的prepare處理程式獲取模組a的所有鎖。
2.呼叫模組b的prepare處理程式獲取模組b的所有鎖。
3.建立子程序。
4.呼叫模組b中的child處理程式釋放子程序中模組b的所有鎖。
5.呼叫模組a中的child處理程式釋放子程序中模組a的所有鎖。
6.fork函式返回到子程序。
7.呼叫模組b中的parent處理程式釋放子程序中模組b的所有鎖。
8.呼叫模組a中的parent處理程式釋放子程序中模組a的所有鎖。
9.fork函式返回到父程序。
下面我們修改下程式:
[cpp]view plain
copy
#include
#include
pthread_mutex_t mutex = pthread_mutex_initializer;
void
child(
void
) void
* th_fn(
void
* arg)
void
ps_fn()
intmain(
void
)
pthread_join(t, 0);
while
(1)
} 執行結果:
yan@yan-vm:~/apue$ ./a.out
start th_fn.
in th_fn.
start ps_fn.
in ps_fn.
end th_fn.
end ps_fn.
《unix環境高階程式設計》筆記2
第四章 檔案和目錄 本章將描述檔案系統特徵和檔案性質 1 stat fstat和lstat函式 原型 include int stat const char restrict pathname,struct stat restrict buf int fstat int filedes,struct...
UNIX環境高階程式設計學習筆記
include include include include int main int argc,char argv err sys can t open s argv 1 while dirp readdir dp null printf s n dirp d name closedir dp ...
unix環境高階程式設計
unix 日曆時間 自1970 年1 月1 日00 00 00 以來的國際標準時間 utc 程序時間 cpu 時間 時鐘時間 程序執行時間的總量。使用者cpu 時間 執行使用者指令時間量。系統cpu 時間 執行核心所經歷時間。命令 time 第三章至第七章 原子操作 任何乙個要求多於1 個函式呼叫的...