第5章并發(fā)服務(wù)器_第1頁(yè)
第5章并發(fā)服務(wù)器_第2頁(yè)
第5章并發(fā)服務(wù)器_第3頁(yè)
第5章并發(fā)服務(wù)器_第4頁(yè)
第5章并發(fā)服務(wù)器_第5頁(yè)
已閱讀5頁(yè),還剩30頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶(hù)提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

1、并發(fā)服務(wù)器目錄n服務(wù)器分類(lèi)技術(shù)n進(jìn)程與線(xiàn)程n多進(jìn)程服務(wù)器n多線(xiàn)程服務(wù)器并發(fā)服務(wù)器服務(wù)器分類(lèi)n按連接類(lèi)型分類(lèi)n面向連接的服務(wù)器(如tcp)n面向無(wú)連接的服務(wù)器(如udp)n按處理方式分類(lèi)n迭代服務(wù)器n并發(fā)服務(wù)器迭代服務(wù)器 vs. 并發(fā)服務(wù)器綁定地址監(jiān)聽(tīng)連接接收連接處理連接斷開(kāi)連接接收請(qǐng)求處理請(qǐng)求返回響應(yīng)綁定地址監(jiān)聽(tīng)連接接收連接創(chuàng)建子進(jìn)程關(guān)閉連接套接字處理連接關(guān)閉連接套接字終止子進(jìn)程關(guān)閉監(jiān)聽(tīng)套接字服務(wù)器主進(jìn)程服務(wù)器子進(jìn)程TCP迭代服務(wù)器TCP并發(fā)服務(wù)器“進(jìn)程”基本概念n進(jìn)程定義了一個(gè)計(jì)算的基本單元,可以認(rèn)為是一個(gè)程序的一次運(yùn)行。它是一個(gè)動(dòng)態(tài)實(shí)體,是獨(dú)立的任務(wù)。它擁有獨(dú)立的地址空間、執(zhí)行堆棧、文件描

2、述符等。n每個(gè)進(jìn)程擁有獨(dú)立的地址空間,進(jìn)程間正常情況下,互不影響,一個(gè)進(jìn)程的崩潰不會(huì)造成其他進(jìn)程的崩潰。n當(dāng)進(jìn)程間共享某一資源時(shí),需注意兩個(gè)問(wèn)題:同步問(wèn)題和通信問(wèn)題。創(chuàng)建進(jìn)程#include #include pid_t fork(void)返回:父進(jìn)程中返回子進(jìn)程的進(jìn)程返回:父進(jìn)程中返回子進(jìn)程的進(jìn)程ID, 子進(jìn)程返回子進(jìn)程返回0, -1出錯(cuò)出錯(cuò)nfork后,子進(jìn)程和父進(jìn)程繼續(xù)執(zhí)行后,子進(jìn)程和父進(jìn)程繼續(xù)執(zhí)行fork()函數(shù)后的指令。()函數(shù)后的指令。子進(jìn)程是父進(jìn)程的副本。子進(jìn)程擁有父進(jìn)程的數(shù)據(jù)空間、子進(jìn)程是父進(jìn)程的副本。子進(jìn)程擁有父進(jìn)程的數(shù)據(jù)空間、堆棧的副本。但父、子進(jìn)程并不共享這些存儲(chǔ)空間部

3、分。堆棧的副本。但父、子進(jìn)程并不共享這些存儲(chǔ)空間部分。如果代碼段是只讀的,則父子進(jìn)程共享代碼段。如果父子如果代碼段是只讀的,則父子進(jìn)程共享代碼段。如果父子進(jìn)程同時(shí)對(duì)同一文件描述字操作,而又沒(méi)有任何形式的同進(jìn)程同時(shí)對(duì)同一文件描述字操作,而又沒(méi)有任何形式的同步,則會(huì)出現(xiàn)混亂的狀況;步,則會(huì)出現(xiàn)混亂的狀況;n父進(jìn)程中調(diào)用父進(jìn)程中調(diào)用fork之前打開(kāi)的所有描述字在函數(shù)之前打開(kāi)的所有描述字在函數(shù)fork返回返回之后子進(jìn)程會(huì)得到一個(gè)副本。之后子進(jìn)程會(huì)得到一個(gè)副本。fork后,父子進(jìn)程均需要將后,父子進(jìn)程均需要將自己不使用的描述字關(guān)閉。自己不使用的描述字關(guān)閉。創(chuàng)建進(jìn)程(cont.)#include #inc

4、lude pid_t vfork(void);n該系統(tǒng)調(diào)用基本上與該系統(tǒng)調(diào)用基本上與fork相同,在相同,在BSD3.0中開(kāi)始出現(xiàn),主中開(kāi)始出現(xiàn),主要為了解決要為了解決fork昂貴的開(kāi)銷(xiāo)。昂貴的開(kāi)銷(xiāo)。n兩者的基本區(qū)別在于當(dāng)使用兩者的基本區(qū)別在于當(dāng)使用vfork()創(chuàng)建新進(jìn)程時(shí),父進(jìn)程創(chuàng)建新進(jìn)程時(shí),父進(jìn)程將被暫時(shí)阻塞,而子進(jìn)程則可以借用父進(jìn)程的地址空間,直將被暫時(shí)阻塞,而子進(jìn)程則可以借用父進(jìn)程的地址空間,直到子進(jìn)程退出,至此父進(jìn)程才繼續(xù)執(zhí)行。到子進(jìn)程退出,至此父進(jìn)程才繼續(xù)執(zhí)行。終止進(jìn)程終止進(jìn)程n進(jìn)程的終止存在兩個(gè)可能:進(jìn)程的終止存在兩個(gè)可能:n父進(jìn)程先于子進(jìn)程終止(父進(jìn)程先于子進(jìn)程終止(init

5、進(jìn)程領(lǐng)養(yǎng))進(jìn)程領(lǐng)養(yǎng))n子進(jìn)程先于主進(jìn)程終止子進(jìn)程先于主進(jìn)程終止n對(duì)于后者,系統(tǒng)內(nèi)核為子進(jìn)程保留一定的狀態(tài)對(duì)于后者,系統(tǒng)內(nèi)核為子進(jìn)程保留一定的狀態(tài)信息:進(jìn)程信息:進(jìn)程ID、終止?fàn)顟B(tài)、終止?fàn)顟B(tài)、CPU時(shí)間等;當(dāng)時(shí)間等;當(dāng)父進(jìn)程調(diào)用父進(jìn)程調(diào)用wait或或waitpid函數(shù)時(shí),獲取這些函數(shù)時(shí),獲取這些信息;(什么叫信息;(什么叫“僵尸進(jìn)程僵尸進(jìn)程”?)?)n當(dāng)子進(jìn)程正?;虍惓=K止時(shí),系統(tǒng)內(nèi)核向其父當(dāng)子進(jìn)程正常或異常終止時(shí),系統(tǒng)內(nèi)核向其父進(jìn)程發(fā)送進(jìn)程發(fā)送SIGCHLD信號(hào);缺省情況下,父進(jìn)信號(hào);缺省情況下,父進(jìn)程忽略該信號(hào),或者提供一個(gè)該信號(hào)發(fā)生時(shí)即程忽略該信號(hào),或者提供一個(gè)該信號(hào)發(fā)生時(shí)即被調(diào)用的函數(shù)。

6、被調(diào)用的函數(shù)。終止進(jìn)程(續(xù))終止進(jìn)程(續(xù))#include void exit(int status);n本函數(shù)終止調(diào)用進(jìn)程。關(guān)閉所有子進(jìn)程打開(kāi)的描述本函數(shù)終止調(diào)用進(jìn)程。關(guān)閉所有子進(jìn)程打開(kāi)的描述符,向父進(jìn)程發(fā)送符,向父進(jìn)程發(fā)送SIGCHLD信號(hào),并返回狀態(tài)。信號(hào),并返回狀態(tài)。獲取子進(jìn)程終止信息獲取子進(jìn)程終止信息#include #include pid_t wait(int *stat_loc); 返回:終止子進(jìn)程的返回:終止子進(jìn)程的ID成功;成功;-1出錯(cuò);出錯(cuò);stat_loc存儲(chǔ)存儲(chǔ)子進(jìn)程的終止?fàn)顟B(tài)(一個(gè)整數(shù));子進(jìn)程的終止?fàn)顟B(tài)(一個(gè)整數(shù));n如果沒(méi)有終止的子進(jìn)程,但是有一個(gè)或多個(gè)正在執(zhí)

7、如果沒(méi)有終止的子進(jìn)程,但是有一個(gè)或多個(gè)正在執(zhí)行的子進(jìn)程,則該函數(shù)將堵塞,直到有一個(gè)子進(jìn)程行的子進(jìn)程,則該函數(shù)將堵塞,直到有一個(gè)子進(jìn)程終止或者終止或者wait被信號(hào)中斷時(shí),被信號(hào)中斷時(shí),wait返回。返回。n當(dāng)調(diào)用該系統(tǒng)調(diào)用時(shí),如果有一個(gè)子進(jìn)程已經(jīng)終止,當(dāng)調(diào)用該系統(tǒng)調(diào)用時(shí),如果有一個(gè)子進(jìn)程已經(jīng)終止,則該系統(tǒng)調(diào)用立即返回,并釋放子進(jìn)程所有資源。則該系統(tǒng)調(diào)用立即返回,并釋放子進(jìn)程所有資源。獲取子進(jìn)程終止信息獲取子進(jìn)程終止信息使用wait()函數(shù)可能會(huì)出現(xiàn)一個(gè)問(wèn)題SIGCHLD服務(wù)器父進(jìn)程服務(wù)器父進(jìn)程服務(wù)器子進(jìn)程服務(wù)器子進(jìn)程服務(wù)器子進(jìn)程服務(wù)器子進(jìn)程服務(wù)器子進(jìn)程服務(wù)器子進(jìn)程客戶(hù)客戶(hù)FINFINFINSI

8、GCHLDSIGCHLD由于由于linux信號(hào)不排隊(duì),在信號(hào)不排隊(duì),在SIGCHLD信號(hào)同時(shí)到來(lái)后,信信號(hào)同時(shí)到來(lái)后,信號(hào)處理程序中調(diào)用了號(hào)處理程序中調(diào)用了wait函數(shù),其只執(zhí)行一次,這樣將留函數(shù),其只執(zhí)行一次,這樣將留下下2個(gè)僵尸進(jìn)程。可以使用個(gè)僵尸進(jìn)程??梢允褂脀aitpid函數(shù)解決這個(gè)問(wèn)題。函數(shù)解決這個(gè)問(wèn)題。獲取子進(jìn)程終止信息獲取子進(jìn)程終止信息pid_t waitpid(pid_t pid, int *stat_loc, int options); 返回:終止子進(jìn)程的返回:終止子進(jìn)程的ID成功;成功;-1出錯(cuò);出錯(cuò);stat_loc存儲(chǔ)存儲(chǔ)子進(jìn)程的終止?fàn)顟B(tài);子進(jìn)程的終止?fàn)顟B(tài);n當(dāng)當(dāng)pid

9、=-1,option=0時(shí),該函數(shù)等同于時(shí),該函數(shù)等同于wait,否則,否則由參數(shù)由參數(shù)pid和和option共同決定函數(shù)行為,其中共同決定函數(shù)行為,其中pid參參數(shù)意義如下:數(shù)意義如下:n-1:要求知道任何一個(gè)子進(jìn)程的返回狀態(tài)(等待第一:要求知道任何一個(gè)子進(jìn)程的返回狀態(tài)(等待第一個(gè)終止的子進(jìn)程);個(gè)終止的子進(jìn)程);n0:要求知道進(jìn)程號(hào)為:要求知道進(jìn)程號(hào)為pid的子進(jìn)程的狀態(tài);的子進(jìn)程的狀態(tài);n-1:要求知道進(jìn)程號(hào)為要求知道進(jìn)程號(hào)為pid的絕對(duì)值的子進(jìn)程的終止的絕對(duì)值的子進(jìn)程的終止?fàn)顟B(tài)狀態(tài) nOptions最常用的選項(xiàng)是最常用的選項(xiàng)是WNOHANG,它通它通知內(nèi)核在沒(méi)有已終止進(jìn)程時(shí)不要堵塞。知

10、內(nèi)核在沒(méi)有已終止進(jìn)程時(shí)不要堵塞。獲取子進(jìn)程終止信息(獲取子進(jìn)程終止信息(cont.)n調(diào)用調(diào)用wait或或waitpid函數(shù)時(shí),正常情況下,函數(shù)時(shí),正常情況下,可能會(huì)有以下幾種情況:可能會(huì)有以下幾種情況:n阻塞(如果其所有子進(jìn)程都還在運(yùn)行);阻塞(如果其所有子進(jìn)程都還在運(yùn)行);n獲得子進(jìn)程的終止?fàn)顟B(tài)并立即返回(如果獲得子進(jìn)程的終止?fàn)顟B(tài)并立即返回(如果一個(gè)子進(jìn)程已終止,正等待父進(jìn)程存取其一個(gè)子進(jìn)程已終止,正等待父進(jìn)程存取其終止?fàn)顟B(tài));終止?fàn)顟B(tài));n出錯(cuò)立即返回(如果它沒(méi)有任何子進(jìn)程)出錯(cuò)立即返回(如果它沒(méi)有任何子進(jìn)程)多進(jìn)程并發(fā)服務(wù)器狀態(tài)圖服務(wù)器客戶(hù)connect()函數(shù)listenfd客戶(hù)/服

11、務(wù)器狀態(tài)圖(調(diào)用accept函數(shù)時(shí))連接請(qǐng)求多進(jìn)程并發(fā)服務(wù)器狀態(tài)圖(cont.)服務(wù)器服務(wù)器客戶(hù)客戶(hù)connect()函數(shù)listenfd客戶(hù)/服務(wù)器狀態(tài)圖(調(diào)用accept函數(shù)后)connfd連接建立多進(jìn)程并發(fā)服務(wù)器狀態(tài)圖(cont.)服務(wù)器(父進(jìn)程)服務(wù)器(父進(jìn)程)客戶(hù)客戶(hù)connect()函數(shù)函數(shù)listenfd客戶(hù)/服務(wù)器狀態(tài)圖(調(diào)用fork函數(shù)后)connfd連接建立連接建立服務(wù)器(子進(jìn)程)listenfdconnfdfork()函數(shù)多進(jìn)程并發(fā)服務(wù)器狀態(tài)圖(cont.)服務(wù)器(父進(jìn)程)服務(wù)器(父進(jìn)程)客戶(hù)客戶(hù)connect()函數(shù)函數(shù)listenfd客戶(hù)/服務(wù)器狀態(tài)圖(父進(jìn)程關(guān)閉連接

12、套接字,子進(jìn)程關(guān)閉監(jiān)聽(tīng)套接字)連接建立服務(wù)器(子進(jìn)程)服務(wù)器(子進(jìn)程)connfd多進(jìn)程并發(fā)服務(wù)器實(shí)例n該實(shí)例包括服務(wù)器程序和客戶(hù)程序,具體功能如下:該實(shí)例包括服務(wù)器程序和客戶(hù)程序,具體功能如下:n服務(wù)器等待接收客戶(hù)的連接請(qǐng)求,一旦連接成功則顯服務(wù)器等待接收客戶(hù)的連接請(qǐng)求,一旦連接成功則顯示客戶(hù)地址,接著接收客戶(hù)端的名稱(chēng)并顯示;然后接示客戶(hù)地址,接著接收客戶(hù)端的名稱(chēng)并顯示;然后接收來(lái)自該客戶(hù)的字符串,每當(dāng)收到一個(gè)字符串時(shí),顯收來(lái)自該客戶(hù)的字符串,每當(dāng)收到一個(gè)字符串時(shí),顯示該字符串,并將字符串按照愷撒密碼的加密方式示該字符串,并將字符串按照愷撒密碼的加密方式(K=3)進(jìn)行加密,再將加密后的字符發(fā)

13、回客戶(hù)端;)進(jìn)行加密,再將加密后的字符發(fā)回客戶(hù)端;之后,繼續(xù)等待接收該客戶(hù)的信息,直到客戶(hù)關(guān)閉連之后,繼續(xù)等待接收該客戶(hù)的信息,直到客戶(hù)關(guān)閉連接。要求服務(wù)器具有同時(shí)處理多個(gè)客戶(hù)請(qǐng)求的能力。接。要求服務(wù)器具有同時(shí)處理多個(gè)客戶(hù)請(qǐng)求的能力。n客戶(hù)首先與相應(yīng)的服務(wù)器建立連接;接著接收用戶(hù)輸客戶(hù)首先與相應(yīng)的服務(wù)器建立連接;接著接收用戶(hù)輸入的客戶(hù)端名稱(chēng),并將其發(fā)送給服務(wù)器;然后繼續(xù)接入的客戶(hù)端名稱(chēng),并將其發(fā)送給服務(wù)器;然后繼續(xù)接收用戶(hù)輸入的字符串,再將字符串發(fā)送給服務(wù)器,同收用戶(hù)輸入的字符串,再將字符串發(fā)送給服務(wù)器,同時(shí)接收服務(wù)器發(fā)回的加密后的字符串并顯示。之后,時(shí)接收服務(wù)器發(fā)回的加密后的字符串并顯示。之

14、后,繼續(xù)等待用戶(hù)輸入字符串,直到用戶(hù)輸入繼續(xù)等待用戶(hù)輸入字符串,直到用戶(hù)輸入Ctrl+D,客,客戶(hù)關(guān)閉連接并退出。戶(hù)關(guān)閉連接并退出。 多進(jìn)程服務(wù)器的問(wèn)題多進(jìn)程服務(wù)器的問(wèn)題 雖然多進(jìn)程并發(fā)服務(wù)器模式很多年來(lái)都使用得雖然多進(jìn)程并發(fā)服務(wù)器模式很多年來(lái)都使用得很好,但使用很好,但使用fork生成子進(jìn)程存在一些問(wèn)題。生成子進(jìn)程存在一些問(wèn)題。n首先,首先,fork占用大量的資源,內(nèi)存映像要從父進(jìn)程占用大量的資源,內(nèi)存映像要從父進(jìn)程拷貝到子進(jìn)程,所有描述符要在子進(jìn)程中復(fù)制等??截惖阶舆M(jìn)程,所有描述符要在子進(jìn)程中復(fù)制等。雖然當(dāng)前采用寫(xiě)時(shí)拷貝(雖然當(dāng)前采用寫(xiě)時(shí)拷貝(copy-on-write)技術(shù),)技術(shù),將真

15、正的拷貝推遲到子進(jìn)程有寫(xiě)操作時(shí),但將真正的拷貝推遲到子進(jìn)程有寫(xiě)操作時(shí),但fork仍仍然需要占用大量資源。然需要占用大量資源。n其次,其次,fork子進(jìn)程后,需要用進(jìn)程間通信(子進(jìn)程后,需要用進(jìn)程間通信(IPC)在父子進(jìn)程間傳遞信息。由于子進(jìn)程從一開(kāi)始就有在父子進(jìn)程間傳遞信息。由于子進(jìn)程從一開(kāi)始就有父進(jìn)程數(shù)據(jù)空間及所有描述符的拷貝,所以父進(jìn)程數(shù)據(jù)空間及所有描述符的拷貝,所以fork之之前的信息容易傳遞,但是從子進(jìn)程返回信息給父進(jìn)前的信息容易傳遞,但是從子進(jìn)程返回信息給父進(jìn)程就需要做很多工作。程就需要做很多工作。 “線(xiàn)程線(xiàn)程”基本概念基本概念n線(xiàn)程是進(jìn)程內(nèi)的獨(dú)立執(zhí)行實(shí)體和調(diào)度單元,又稱(chēng)為線(xiàn)程是進(jìn)程

16、內(nèi)的獨(dú)立執(zhí)行實(shí)體和調(diào)度單元,又稱(chēng)為“輕量級(jí)輕量級(jí)”進(jìn)程(進(jìn)程(lightwight process);創(chuàng)建線(xiàn)程比進(jìn)程快);創(chuàng)建線(xiàn)程比進(jìn)程快10100倍。一個(gè)進(jìn)程內(nèi)的所有線(xiàn)程共享相同的內(nèi)存空間、倍。一個(gè)進(jìn)程內(nèi)的所有線(xiàn)程共享相同的內(nèi)存空間、全局變量等信息(這種機(jī)制又帶來(lái)了同步問(wèn)題)。而且它們?nèi)肿兞康刃畔ⅲㄟ@種機(jī)制又帶來(lái)了同步問(wèn)題)。而且它們還共享以下信息:還共享以下信息: 共享信息共享信息 私有信息私有信息n進(jìn)程指令進(jìn)程指令 線(xiàn)程線(xiàn)程IDn大多數(shù)數(shù)據(jù)大多數(shù)數(shù)據(jù) 寄存器集合(包括程序計(jì)數(shù)器和棧指針)寄存器集合(包括程序計(jì)數(shù)器和棧指針)n打開(kāi)的文件描述字打開(kāi)的文件描述字棧(用于存放局部變量)棧(用于

17、存放局部變量)n信號(hào)處理程序和信號(hào)處置信號(hào)處理程序和信號(hào)處置errorn當(dāng)前工作目錄當(dāng)前工作目錄信號(hào)掩碼信號(hào)掩碼n用戶(hù)用戶(hù)ID和組和組ID優(yōu)先級(jí)優(yōu)先級(jí)線(xiàn)程調(diào)用函數(shù)(1)#include int pthread_create(pthread_t *tid, const pthread_attr_t *attr, void *(*func)(void *), void *arg); 返回:成功時(shí)為返回:成功時(shí)為0;出錯(cuò)時(shí)為正的;出錯(cuò)時(shí)為正的Exxx值值n當(dāng)一個(gè)程序開(kāi)始運(yùn)行時(shí),系統(tǒng)會(huì)創(chuàng)建一個(gè)初始線(xiàn)程或主線(xiàn)程當(dāng)一個(gè)程序開(kāi)始運(yùn)行時(shí),系統(tǒng)會(huì)創(chuàng)建一個(gè)初始線(xiàn)程或主線(xiàn)程的單個(gè)線(xiàn)程。額外線(xiàn)程由上述函數(shù)創(chuàng)建;的單個(gè)

18、線(xiàn)程。額外線(xiàn)程由上述函數(shù)創(chuàng)建;n新線(xiàn)程由線(xiàn)程新線(xiàn)程由線(xiàn)程id標(biāo)識(shí):標(biāo)識(shí):tid,新線(xiàn)程的屬性,新線(xiàn)程的屬性attr包括:優(yōu)先級(jí)、包括:優(yōu)先級(jí)、初始棧大小、是否應(yīng)該是守護(hù)線(xiàn)程等等。線(xiàn)程的執(zhí)行函數(shù)和初始棧大小、是否應(yīng)該是守護(hù)線(xiàn)程等等。線(xiàn)程的執(zhí)行函數(shù)和調(diào)用參數(shù)分別是:調(diào)用參數(shù)分別是:func和和arg;n由于線(xiàn)程的執(zhí)行函數(shù)的參數(shù)和返回值類(lèi)型均為由于線(xiàn)程的執(zhí)行函數(shù)的參數(shù)和返回值類(lèi)型均為void *,因此,因此可傳遞和返回指向任何類(lèi)型的指針;可傳遞和返回指向任何類(lèi)型的指針;n常見(jiàn)的返回錯(cuò)誤值:常見(jiàn)的返回錯(cuò)誤值:EAGAIN:超過(guò)了系統(tǒng)線(xiàn)程數(shù)目的限制。:超過(guò)了系統(tǒng)線(xiàn)程數(shù)目的限制。ENOMEN:沒(méi)有足夠的內(nèi)

19、存產(chǎn)生新的線(xiàn)程。:沒(méi)有足夠的內(nèi)存產(chǎn)生新的線(xiàn)程。EINVAL:無(wú)效的屬性:無(wú)效的屬性attr值。值。線(xiàn)程函數(shù)調(diào)用(線(xiàn)程函數(shù)調(diào)用(2)#inlcude int pthread_join(pthread_t tid, void *status); 返回:成功時(shí)為返回:成功時(shí)為0;出錯(cuò)時(shí)為正的;出錯(cuò)時(shí)為正的Exxx值,不值,不設(shè)置設(shè)置errorn該函數(shù)類(lèi)似與該函數(shù)類(lèi)似與waitpid函數(shù),但必須指定等函數(shù),但必須指定等待線(xiàn)程的待線(xiàn)程的ID,該函數(shù)不能等待任意一個(gè)線(xiàn)程,該函數(shù)不能等待任意一個(gè)線(xiàn)程結(jié)束(如結(jié)束(如wait););n被等待線(xiàn)程必須是當(dāng)前進(jìn)程的成員,并且不被等待線(xiàn)程必須是當(dāng)前進(jìn)程的成員,并且不

20、是是分離的線(xiàn)程分離的線(xiàn)程和和守護(hù)線(xiàn)程守護(hù)線(xiàn)程。pthread_t pthread_self(void); 返回:調(diào)用線(xiàn)程的線(xiàn)程返回:調(diào)用線(xiàn)程的線(xiàn)程id;線(xiàn)程函數(shù)調(diào)用(3)#include int pthread_detach(pthread_t tid) 返回:成功時(shí)為返回:成功時(shí)為0;出錯(cuò)時(shí)為正;出錯(cuò)時(shí)為正Exxx值;值;n線(xiàn)程或者是可匯合的(線(xiàn)程或者是可匯合的(joinable)(默認(rèn)),或者)(默認(rèn)),或者是脫離的(是脫離的(detached)。當(dāng)可匯合的線(xiàn)程終止時(shí),)。當(dāng)可匯合的線(xiàn)程終止時(shí),其線(xiàn)程其線(xiàn)程id和退出狀態(tài)將保留,直到另外一個(gè)線(xiàn)程調(diào)用和退出狀態(tài)將保留,直到另外一個(gè)線(xiàn)程調(diào)用pt

21、hread_join。脫離的線(xiàn)程則像守護(hù)進(jìn)程,當(dāng)它終。脫離的線(xiàn)程則像守護(hù)進(jìn)程,當(dāng)它終止時(shí),釋放所有資源,我們不能等待它終止。止時(shí),釋放所有資源,我們不能等待它終止。n該函數(shù)將指定的線(xiàn)程變?yōu)槊撾x的。該函數(shù)將指定的線(xiàn)程變?yōu)槊撾x的。 pthread_detach(pthread_self()();線(xiàn)程函數(shù)調(diào)用(線(xiàn)程函數(shù)調(diào)用(4)#include void pthread_exit(void *status); 無(wú)返回值;無(wú)返回值;n如果線(xiàn)程為可匯合的,將保留線(xiàn)程如果線(xiàn)程為可匯合的,將保留線(xiàn)程id和退出狀態(tài)供和退出狀態(tài)供pthread_join()函數(shù)調(diào)用()函數(shù)調(diào)用;n指針指針status:指向線(xiàn)程

22、的退出狀態(tài)。不能指向一個(gè)局部:指向線(xiàn)程的退出狀態(tài)。不能指向一個(gè)局部變量,因?yàn)榫€(xiàn)程終止時(shí)其所有的局部變量將被撤銷(xiāo);變量,因?yàn)榫€(xiàn)程終止時(shí)其所有的局部變量將被撤銷(xiāo);n還有其他兩種方法可使線(xiàn)程終止還有其他兩種方法可使線(xiàn)程終止n啟動(dòng)線(xiàn)程的函數(shù)(啟動(dòng)線(xiàn)程的函數(shù)(pthread_create的第的第3個(gè)參數(shù))個(gè)參數(shù))返回。其返回值便是線(xiàn)程的終止?fàn)顟B(tài);返回。其返回值便是線(xiàn)程的終止?fàn)顟B(tài);n如果進(jìn)程的如果進(jìn)程的main函數(shù)返回,或者當(dāng)前進(jìn)程中,任一函數(shù)返回,或者當(dāng)前進(jìn)程中,任一線(xiàn)程調(diào)用了線(xiàn)程調(diào)用了exit()函數(shù),將終止該進(jìn)程中所有線(xiàn)()函數(shù),將終止該進(jìn)程中所有線(xiàn)程。程。給新線(xiàn)程傳遞參數(shù)n由于同一個(gè)進(jìn)程內(nèi)的所有線(xiàn)

23、程共享內(nèi)存和變量,因此在傳遞參數(shù)時(shí)需作特殊處理,下面參考如下幾種方法:n傳遞參數(shù)的普通方法n通過(guò)指針傳遞參數(shù)n通過(guò)分配arg的空間來(lái)傳遞參數(shù)傳遞參數(shù)的普通方法n由于線(xiàn)程創(chuàng)建函數(shù)只允許傳遞一個(gè)參數(shù),因此當(dāng)需要傳遞多個(gè)數(shù)據(jù)時(shí),應(yīng)首先將這些數(shù)據(jù)由于線(xiàn)程創(chuàng)建函數(shù)只允許傳遞一個(gè)參數(shù),因此當(dāng)需要傳遞多個(gè)數(shù)據(jù)時(shí),應(yīng)首先將這些數(shù)據(jù)封裝在一個(gè)結(jié)構(gòu)中。封裝在一個(gè)結(jié)構(gòu)中。void *start_routine(void *arg);struct ARG int connfd;int other;int main() ARG arg;While(1) if(connfd = accept(sockfd,NULL,NU

24、LL)= -1) arg.connfd = connfd; pthread_create(&tid, NULL, start_routine, (void *)&arg); void *start_routine(void *arg) ARG info;info.connfd = (ARG *)arg) - connfd;info.other = (ARG *)arg) - other;/這種方法有問(wèn)題,對(duì)一個(gè)客戶(hù)可以工作,但多個(gè)客戶(hù)則可能出現(xiàn)問(wèn)題。這種方法有問(wèn)題,對(duì)一個(gè)客戶(hù)可以工作,但多個(gè)客戶(hù)則可能出現(xiàn)問(wèn)題。 通過(guò)指針傳遞參數(shù)n這種方法首先將要傳遞的數(shù)據(jù)轉(zhuǎn)換成通用指針類(lèi)型,然

25、后傳遞給新線(xiàn)程,這種方法首先將要傳遞的數(shù)據(jù)轉(zhuǎn)換成通用指針類(lèi)型,然后傳遞給新線(xiàn)程,新線(xiàn)程再將其還原成原數(shù)據(jù)類(lèi)型:新線(xiàn)程再將其還原成原數(shù)據(jù)類(lèi)型:void *start_routine(void *arg);int main(void) int connfd;pthread_create(&tid, NULL, start_routine, (void *)connfd);void *start_routine(void *arg) int connfd;connfd =(int ) arg;n這種方法雖然簡(jiǎn)單,但卻有這種方法雖然簡(jiǎn)單,但卻有。如:要求。如:要求arg的類(lèi)型必須能的類(lèi)型必須能

26、被正確地轉(zhuǎn)換成通用指針類(lèi)型,而且可傳遞的參數(shù)只有一個(gè)。被正確地轉(zhuǎn)換成通用指針類(lèi)型,而且可傳遞的參數(shù)只有一個(gè)。通過(guò)分配arg的空間來(lái)傳遞n主線(xiàn)程首先為每個(gè)新線(xiàn)程分配存儲(chǔ)主線(xiàn)程首先為每個(gè)新線(xiàn)程分配存儲(chǔ)arg的空間,再將的空間,再將arg傳遞給新線(xiàn)程傳遞給新線(xiàn)程使用,新線(xiàn)程使用完后要釋放該空間。使用,新線(xiàn)程使用完后要釋放該空間。void *start_routine(void *arg);int main(void) ARG * arg;int connfd; loop if(connfd = accept(sockfd,NULL,NULL)= -1) arg = new ARG;arg - con

27、nfd = connfd;pthread_create(&tid, NULL, start_routine, (void *)arg);線(xiàn)程安全問(wèn)題n線(xiàn)程安全問(wèn)題是一個(gè)非常復(fù)雜的問(wèn)題。簡(jiǎn)單地說(shuō),就是多個(gè)線(xiàn)程在操作共享數(shù)據(jù)時(shí)出現(xiàn)的混亂情況,這種情況可能導(dǎo)致不可預(yù)測(cè)的后果。n解決線(xiàn)程安全問(wèn)題的方法主要有兩種:一是使用線(xiàn)程安全函數(shù):posix定義的以”_r”結(jié)尾的函數(shù),二是使用線(xiàn)程專(zhuān)用數(shù)據(jù)(TSD)。線(xiàn)程專(zhuān)用數(shù)據(jù):TSDn從上例可以看出,在多線(xiàn)程環(huán)境中,應(yīng)避免使用靜態(tài)變量。在linux環(huán)境中,用線(xiàn)程專(zhuān)用數(shù)據(jù)TSD取代靜態(tài)變量。它類(lèi)似于全局?jǐn)?shù)據(jù),只不過(guò)它是線(xiàn)程私有的,是以線(xiàn)程為界限的。TSD是定義線(xiàn)程私有全局?jǐn)?shù)據(jù)的唯一方法。n每個(gè)TSD由進(jìn)程內(nèi)唯一的關(guān)鍵字(key)來(lái)標(biāo)志,用這個(gè)關(guān)鍵字,線(xiàn)程可以存取線(xiàn)程私有的數(shù)據(jù)。pthread_key_create函數(shù)#include int pthread_key_cr

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶(hù)所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶(hù)上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶(hù)上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶(hù)因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論