posix 線程(一):線程模型、pthread 系列函數 和 簡單多線程服務器端程序

posix 線程(一):線程模型、pthread 系列函數 和 簡單多線程服務器端程序

 

1、線程有3種模型,分別是N:1用戶線程模型,1:1核心線程模型和N:M混合線程模型,posix thread屬於1:1模型。html


(一)、N:1用戶線程模型linux

「線程實現」創建在「進程控制」機制之上,由用戶空間的程序庫來管理。OS內核徹底不知道線程信息。這些線程稱爲用戶空間線程。這些線程都工做在「進編程

程競爭範圍」(process contention scope):各個線程在同一進程競爭「被調度的CPU時間」(但不直接和其餘進程中的線程競爭)。
服務器



在N:1線程模型中,內核不干涉線程的任何生命活動,也不干涉同一進程中的線程環境切換。
網絡

在N:1線程模型中,一個進程中的多個線程只能調度到一個CPU,這種約束限制了可用的並行總量。
多線程

第二個缺點是若是某個線程執行了一個「阻塞式」操做(如read),那麼,進程中的全部線程都會阻塞,直至那個操做結束。爲此,一些線程的實現是爲函數

這些阻塞式函數提供包裝器,用非阻塞版本替換這些系統調用,以消除這種限制。
性能


(二)、1:1核心線程模型 pthread線程庫--NPTL(Native POSIX Threading Library)學習

在1:1核心線程模型中,應用程序建立的每個線程(也有書稱爲LWP)都由一個核心線程直接管理。OS內核將每個核心線程都調到系統CPU上,網站

所以,全部線程都工做在「系統競爭範圍」(system contention scope):線程直接和「系統範圍」內的其餘線程競爭。

這種線程的建立與調度由內核完成,由於這種線程的系統開銷比較大(但通常來講,比進程開銷小)




(三)、N:M混合線程模型  NGPT(Next Generation POSIX Threads)

N:M混合線程模型提供了兩級控制,將用戶線程映射爲系統的可調度體以實現並行,這個可調度體稱爲輕量級進程(LWP:light weight process),LWP
再一一映射到核心線程。以下圖所示。OS內核將每個核心線程都調到系統CPU上,所以,全部線程都工做在「系統競爭範圍」。


聽說一些類UNIX系統(如Solaris)已經實現了比較成熟的M:N線程模型, 其性能比起linux的線程仍是有着必定的優點,但不能利用SMP結構。

按照2003年3月NGPT官方網站上的通知,NGPT考慮到NPTL日益普遍地爲人所接受,爲避免不一樣的線程庫版本引發的混亂,從此將再也不進行進一步開發,而今進行支持性的維護工做。也就是說,NGPT已經放棄與NPTL競爭下一代Linux POSIX線程庫標準。


2、posix 線程概述

咱們知道,進程在各自獨立的地址空間中運行,進程之間共享數據須要用進程間通訊機制,有些狀況須要在一個進程中同時執行多個控制流程,這時候

線程就派上了用場,好比實現一個圖形界面的下載軟件,一方面須要和用戶交互,等待和處理用戶的鼠標鍵盤事件,另外一方面又須要同時下載多個文

件,等待和處理從多個網絡主機發來的數據,這些任務都須要一個「等待-處理」的循環,能夠用多線程實現,一個線程專門負責與用戶交互,另外幾個線

程每一個線程負責和一個網絡主機通訊。


之前咱們講過,main函數和信號處理函數是同一個進程地址空間中的多個控制流程,多線程也是如此,可是比信號處理函數更加靈活,信號處理函數的

控制流程只是在信號遞達時產生,在處理完信號以後就結束,而多線程的控制流程能夠長期並存,操做系統會在各線程之間調度和切換,就像在多個進

程之間調度和切換同樣。因爲同一進程的多個線程共享同一地址空間,所以Text Segment、Data Segment都是共享的,若是定義一個函數,在各線程

中均可以調用,若是定義一個全局變量,在各線程中均可以訪問到,除此以外,各線程還共享如下進程資源和環境:


文件描述符表

每種信號的處理方式(SIG_IGN、SIG_DFL或者自定義的信號處理函數)

當前工做目錄

用戶id和組id


但有些資源是每一個線程各有一份的:

線程id

上下文,包括各類寄存器的值、程序計數器和棧指針

棧空間

errno變量

信號屏蔽字

調度優先級


咱們將要學習的線程庫函數是由POSIX標準定義的,稱爲POSIX thread或者pthread。在Linux上線程函數位於libpthread共享庫中,所以在編譯時要加上-lpthread選項。


注:linux 2.6 之後的線程就是由用戶態的pthread庫實現的.使用pthread之後在用戶看來每個task_struct就對應一個線程而一組線程以及它們所共同引用的一組資源就是一個進程.在linux 2.6中, 內核有了線程組的概念, task_struct結構中增長了一個tgid(thread group id)字段. getpid(獲取進程ID)系統調用返回的也是tast_struct中的tgid, 而tast_struct中的pid則由gettid系統調用來返回。

當線程中止/繼續, 或者是收到一個致命信號時, 內核會將處理動做施加到整個線程組中。
比 如程序a.out運行時,建立了一個線程。假設主線程的pid是1000一、子線程是10002(它們的tgid都是10001)。這時若是你kill 10002,是能夠把10001和10002這兩個線程一塊兒殺死的,儘管執行ps命令的時候根本看不到10002這個進程。若是你不知道linux線程背 後的故事,確定會以爲遇到靈異事件了。
 
 

參考:

《linux c 編程一站式學習》

《UNP》

《APUE》

http://www.ibm.com/developerworks/cn/linux/l-cn-mthreadps/index.html

http://hi.baidu.com/_kouu/item/282b80a933ccc3a829ce9dd9

http://www.ibm.com/developerworks/cn/linux/kernel/l-thread/
相關文章
相關標籤/搜索