pthread多線程編程整理(二)

轉載 pthread多線程編程整理(二)收藏

<script></script>

補充:

在傳統的Unix模型中,當一個進程需要由另一個實體執行某件事時,該進程派生(fork)一個子進程,讓子進程去進行處理。Unix下的大多數網絡服務器程序都是這麼編寫的,即父進程接受連接,派生子進程,子進程處理與客戶的交互。

雖然這種模型很多年來使用得很好,但是fork時有一些問題:

1. fork是昂貴的。內存映像要從父進程拷貝到子進程,所有描述字要在子進程中複製等等。目前有的Unix實現使用一種叫做寫時拷貝(copy-on-write)的技術,可避免父進程數據空間向子進程的拷貝。儘管有這種優化技術,fork仍然是昂貴的。

2. fork子進程後,需要用進程間通信(IPC)在父子進程之間傳遞信息。Fork之前的信息容易傳遞,因爲子進程從一開始就有父進程數據空間及所有描述字的拷貝。但是從子進程返回信息給父進程需要做更多的工作。

線程有助於解決這兩個問題。線程有時被稱爲輕權進程(lightweight process),因爲線程比進程“輕權”,一般來說,創建一個線程要比創建一個進程快10~100倍。

一個進程中的所有線程共享相同的全局內存,這使得線程很容易共享信息,但是這種簡易性也帶來了同步問題。

一個進程中的所有線程不僅共享全局變量,而且共享:進程指令、大多數數據、打開的文件(如描述字)、信號處理程序和信號處置、當前工作目錄、用戶ID和組ID。但是每個線程有自己的線程ID、寄存器集合(包括程序計數器和棧指針)、棧(用於存放局部變量和返回地址)、error、信號掩碼、優先級。在Linux中線程編程符合Posix.1標準,稱爲Pthreads。所有的pthread函數都以pthread_開頭。以下先講述5個基本線程函數,在調用它們前均要包括pthread.h頭文件。然後再給出用它們編寫的一個TCP客戶/服務器程序例子。

第一個函數:

 

int pthread_create (pthread_t *tid,const pthread_attr_t *attr,void *      (*func)(void *),void *arg);

一個進程中的每個線程都由一個線程ID(thread ID)標識,其數據類型是pthread_t(常常是unsigned int)。如果新的線程創建成功,其ID將通過tid指針返回。

每個線程都有很多屬性:優先級、起始棧大小、是否應該是一個守護線程等等,當創建線程時,我們可通過初始化一個pthread_attr_t變量說明這些屬性以覆蓋缺省值。我們通常使用缺省值,在這種情況下,我們將attr參數說明爲空指針。

最後,當創建一個線程時,我們要說明一個它將執行的函數。線程以調用該函數開始,然後或者顯式地終止(調用pthread_exit)或者隱式地終止(讓該函數返回)。函數的地址由func參數指定,該函數的調用參數是一個指針arg,如果我們需要多個調用參數,我們必須將它們打包成一個結構,然後將其地址當作唯一的參數傳遞給起始函數。

在func和arg的聲明中,func函數取一個通用指針(void *)參數,並返回一個通用指針(void *),這就使得我們可以傳遞一個指針(指向任何我們想要指向的東西)給線程,由線程返回一個指針(同樣指向任何我們想要指向的東西)。調用成功,返回0,出錯時返回正Exxx值。Pthread函數不設置errno。

第二個函數:

 

int pthread_join(pthread_t tid,void **status);

該函數等待一個線程終止。把線程和進程相比,pthread_creat類似於fork,而pthread_join類似於waitpid。我們必須要等待線程的tid,很可惜,我們沒有辦法等待任意一個線程結束。如果status指針非空,線程的返回值(一個指向某個對象的指針)將存放在status指向的位置。

第三個函數:

 

pthread_t pthread_self(void);

線程都有一個ID以在給定的進程內標識自己。線程ID由pthread_creat返回,我們可以pthread_self取得自己的線程ID。

第四個函數:

 

int pthread_detach(pthread_t tid);

線程或者是可匯合的(joinable)或者是脫離的(detached)。當可匯合的線程終止時,其線程ID和退出狀態將保留,直到另外一個線程調用pthread_join。脫離的線程則像守護進程:當它終止時,所有的資源都釋放,我們不能等待它終止。如果一個線程需要知道另一個線程什麼時候終止,最好保留第二個線程的可匯合性。Pthread_detach函數將指定的線程變爲脫離的。該函數通常被想脫離自己的線程調用,如:pthread_detach (pthread_self ( ));

 




 

第五個函數:

void pthread_exit(void *status);

該函數終止線程。如果線程未脫離,其線程ID和退出狀態將一直保留到調用進程中的某個其他線程調用pthread_join函數。指針status不能指向局部於調用線程的對象,因爲線程終止時這些對象也消失。有兩種其他方法可使線程終止:

1. 啓動線程的函數(pthread_creat的第3個參數)返回。既然該函數必須說明爲返回一個void指針,該返回值便是線程的終止狀態。

2. 如果進程的main函數返回或者任何線程調用了exit,進程將終止,線程將隨之終止。

 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章