<a href="http://blog.csdn.net/gatieme/article/details/51481863#t0">線程與程序概念</a>
<a href="http://blog.csdn.net/gatieme/article/details/51481863#t1">線程概念的産生</a>
<a href="http://blog.csdn.net/gatieme/article/details/51481863#t2">傳統單線程程序的缺點</a>
<a href="http://blog.csdn.net/gatieme/article/details/51481863#t3">多線程的優缺點</a>
<a href="http://blog.csdn.net/gatieme/article/details/51481863#t4">線程的設計過程演變</a>
<a href="http://blog.csdn.net/gatieme/article/details/51481863#t5">SMP機器上多線程的并行性</a>
<a href="http://blog.csdn.net/gatieme/article/details/51481863#t6">線程模型核心級線程和使用者級線程</a>
<a href="http://blog.csdn.net/gatieme/article/details/51481863#t7">目前的實作政策</a>
<a href="http://blog.csdn.net/gatieme/article/details/51481863#t8">三種線程概念核心線程輕量級程序使用者線程</a>
<a href="http://blog.csdn.net/gatieme/article/details/51481863#t9">核心線程</a>
<a href="http://blog.csdn.net/gatieme/article/details/51481863#t10">輕量級程序</a>
<a href="http://blog.csdn.net/gatieme/article/details/51481863#t11">使用者線程</a>
<a href="http://blog.csdn.net/gatieme/article/details/51481863#t12">加強版的使用者線程使用者線程LWP</a>
<a href="http://blog.csdn.net/gatieme/article/details/51481863#t13">Linux使用的線程庫</a>
轉載 <a href="http://www.cnitblog.com/tarius.wu/articles/2277.html" target="_blank">關于程序、線程和輕量級程序的一些筆記</a>
程序是資源管理的最小單元;
線程是程式執行的最小單元。
即線程作為排程和配置設定的基本機關,程序作為資源配置設定的基本機關
一個程序的組成實體可以分為兩大部分:線程集和資源集。程序中的線程是動态的對象;代表了程序指令的執行。資源,包括位址空間、打開的檔案、使用者資訊等等,由程序内的線程共享。
傳統的UNIX程序是單線程的,單線程意味着程式必須是順序執行,不能并發;既在一個時刻隻能運作在一個處理器上,是以不能充分利用多處理器架構的計算機。
如果采用多程序的方法,則有如下問題:
fork一個子程序的消耗是很大的,fork是一個昂貴的系統調用,即使使用現代的寫時複制(copy-on-write)技術。
各個程序擁有自己獨立的位址空間,程序間的協作需要複雜的IPC技術,如消息傳遞和共享記憶體等。
多線程的優點和缺點實際上是對立統一的。
支援多線程的程式(程序)可以取得真正的并行(parallelism),且由于共享程序的代碼和全局資料,故線程間的通信是友善的。它的缺點也是由于線程共享程序的位址空間,是以可能會導緻競争,是以對某一塊有多個線程要通路的資料需要一些同步技術。
在作業系統設計上,從程序演化出線程,最主要的目的就是更好的支援SMP以及減小(程序/線程)上下文切換開銷。
無論按照怎樣的分法,一個程序至少需要一個線程作為它的指令執行體,程序管理着資源(比如cpu、記憶體、檔案等等),而将線程配置設定到某個cpu上執 行。
一個程序當然可以擁有多個線程,此時,如果程序運作在SMP機器上,它就可以同時使用多個cpu來執行各個線程,達到最大程度的并行,以提高效率;同 時,即使是在單cpu的機器上,采用多線程模型來設計程式,正如當年采用多程序模型代替單程序模型一樣,使設計更簡潔、功能更完備,程式的執行效率也更 高,例如采用多個線程響應多個輸入,而此時多線程模型所實作的功能實際上也可以用多程序模型來實作,而與後者相比,線程的上下文切換開銷就比程序要小多 了,從語義上來說,同時響應多個輸入這樣的功能,實際上就是共享了除cpu以外的所有資源的。
針對線程模型的兩大意義,分别開發出了核心級線程和使用者級線程兩種線程模型,分類的标準主要是線程的排程者在核内還是在核外。前者更利于并發使用多處理器的資源,而後者則更多考慮的是上下文切換開銷。
在目前的商用系統中,通常都将兩者結合起來使用,既提供核心線程以滿足smp系統的需要,也支援用線 程庫的方式在使用者态實作另一套線程機制,此時一個核心線程同時成為多個使用者态線程的排程者。
線上程機制的具體實作上,可以在作業系統核心上實作線程,也可以在核外實作,後者顯然要求核内至少實作了程序,而前者則一般要求在核内同時也支援進 程。核心級線程模型顯然要求前者的支援,而使用者級線程模型則不一定基于後者實作。這種差異,正如前所述,是兩種分類方式的标準不同帶來的。
當核内既支援程序也支援線程時,就可以實作線程-程序的”多對多”模型,即一個程序的某個線程由核内排程,而同時它也可以作為使用者級線程池的排程 者,選擇合适的使用者級線程在其空間中運作。這就是前面提到的”混合”線程模型,既可滿足多處理機系統的需要,也可以最大限度的減小排程開銷。
核心線程就是核心的分身,一個分身可以處理一件特定事情。這在處理異步事件如異步IO時特别有用。核心線程的使用是廉價的,唯一使用的資源就是核心棧和上下文切換時儲存寄存器的空間。支援多線程的核心叫做多線程核心(Multi-Threads kernel )。
核心線程隻運作在核心态,不受使用者态上下文的拖累。
處理器競争:可以在全系統範圍内競争處理器資源;
使用資源:唯一使用的資源是核心棧和上下文切換時保持寄存器的空間
排程:排程的開銷可能和程序自身差不多昂貴
同步效率:資源的同步和資料共享比整個程序的資料同步和共享要低一些。
輕量級程序(LWP)是建立在核心之上并由核心支援的使用者線程,它是核心線程的高度抽象,每一個輕量級程序都與一個特定的核心線程關聯。核心線程隻能由核心管理并像普通程序一樣被排程。
a LWP runs in user space on top of a single kernel thread and shares its address space and system resources with other LWPs within the same process
輕量級程序由clone()系統調用建立,參數是CLONE_VM,即與父程序是共享程序位址空間和系統資源。
與普通程序差別:LWP隻有一個最小的執行上下文和排程程式所需的統計資訊。
處理器競争:因與特定核心線程關聯,是以可以在全系統範圍内競争處理器資源
使用資源:與父程序共享程序位址空間
排程:像普通程序一樣排程
輕量級線程(LWP)是一種由核心支援的使用者線程。它是基于核心線程的進階抽象,是以隻有先支援核心線程,才能有LWP。每一個程序有一個或多個LWPs,每個LWP由一個核心線程支援。這種模型實際上就是恐龍書上所提到的一對一線程模型。在這種實作的作業系統中,LWP就是使用者線程。
由于每個LWP都與一個特定的核心線程關聯,是以每個LWP都是一個獨立的線程排程單元。即使有一個LWP在系統調用中阻塞,也不會影響整個程序的執行。
輕量級程序具有局限性。
首先,大多數LWP的操作,如建立、析構以及同步,都需要進行系統調用。系統調用的代價相對較高:需要在user mode和kernel mode中切換。
其次,每個LWP都需要有一個核心線程支援,是以LWP要消耗核心資源(核心線程的棧空間)。是以一個系統不能支援大量的LWP。

注: LWP的術語是借自于SVR4/MP和Solaris 2.x。 有些系統将LWP稱為虛拟處理器。 将之稱為輕量級程序的原因可能是:在核心線程的支援下,LWP是獨立的排程單元,就像普通的程序一樣。是以LWP的最大特點還是每個LWP都有一個核心線程支援。
使用者線程是完全建立在使用者空間的線程庫,使用者線程的建立、排程、同步和銷毀全又庫函數在使用者空間完成,不需要核心的幫助。是以這種線程是極其低消耗和高效的。
處理器競争:單純的使用者線程是建立在使用者空間,其對核心是透明的,是以其所屬程序單獨參與處理器的競争,而程序的所有線程參與競争該程序的資源。
使用資源:與所屬程序共享程序位址空間和系統資源。
排程:由在使用者空間實作的線程庫,在所屬程序内進行排程
LWP雖然本質上屬于使用者線程,但LWP線程庫是建立在核心之上的,LWP的許多操作都要進行系統調用,是以效率不高。而這裡的使用者線程指的是完全建立在使用者空間的線程庫,使用者線程的建立,同步,銷毀,排程完全在使用者空間完成,不需要核心的幫助。是以這種線程的操作是極其快速的且低消耗的。
上圖是最初的一個使用者線程模型,從中可以看出,程序中包含線程,使用者線程在使用者空間中實作,核心并沒有直接對使用者線程程序排程,核心的排程對象和傳統程序一樣,還是程序本身,核心并不知道使用者線程的存在。
使用者線程之間的排程由在使用者空間實作的線程庫實作。
這種模型對應着恐龍書中提到的多對一線程模型,其缺點是一個使用者線程如果阻塞在系統調用中,則整個程序都将會阻塞。
這種模型對應着恐龍書中多對多模型。
使用者線程庫還是完全建立在使用者空間中,是以使用者線程的操作還是很廉價,是以可以建立任意多需要的使用者線程。
作業系統提供了LWP作為使用者線程和核心線程之間的橋梁。LWP還是和前面提到的一樣,具有核心線程支援,是核心的排程單元,并且使用者線程的系統調用要通過LWP,是以程序中某個使用者線程的阻塞不會影響整個程序的執行。
使用者線程庫将建立的使用者線程關聯到LWP上,LWP與使用者線程的數量不一定一緻。當核心排程到某個LWP上時,此時與該LWP關聯的使用者線程就被執行。
LinuxThreads是使用者空間的線程庫,所采用的是線程-程序1對1模型(即一個使用者線程對應一個輕量級程序,而一個輕量級程序對應一個特定的核心線程),将線程的排程等同于程序的排程,排程交由核心完成,而線程的建立、同步、銷毀由核外線程庫完成(LinuxThtreads已綁定到 GLIBC中發行)。
在LinuxThreads中,由專門的一個管理線程處理所有的線程管理工作。當程序第一次調用pthread_create()建立線程時就會先 建立(clone())并啟動管理線程。後續程序pthread_create()建立線程時,都是管理線程作為pthread_create()的調用者的子線程,通過調用clone()來建立使用者線程,并記錄輕量級程序号和線程id的映射關系,是以,使用者線程其實是管理線程的子線程。
LinuxThreads隻支援排程範圍為PTHREAD_SCOPE_SYSTEM的排程,預設的排程政策是SCHED_OTHER。
使用者線程排程政策也可修改成SCHED_FIFO或SCHED_RR方式,這兩種方式支援優先級為0-99,而SCHED_OTHER隻支援0。
SCHED_OTHER 分時排程政策,
SCHED_FIFO 實時排程政策,先到先服務
SCHED_RR 實時排程政策,時間片輪轉
SCHED_OTHER是普通程序的,後兩個是實時程序的(一般的程序都是普通程序,系統中出現實時程序的機會很少)。SCHED_FIFO、 SCHED_RR優先級高于所有SCHED_OTHER的程序,是以隻要他們能夠運作,在他們運作完之前,所有SCHED_OTHER的程序的都沒有得到 執行的機會
小結: 很多文獻中都認為輕量級程序就是線程,實際上這種說法并不完全正确,從前面的分析中可以看到,隻有在使用者線程完全由輕量級程序構成時,才可以說輕量級程序就是線程。 本文轉自張昺華-sky部落格園部落格,原文連結:http://www.cnblogs.com/sky-heaven/p/7050983.html,如需轉載請自行聯系原作者