1. 程式人生 > >線程詳細剖析(四)

線程詳細剖析(四)

最大 ++ suse 提高 局部變量 att 分配 osi 分離

摘自《C++多核編程》

6.3 設置線程屬性

存在一些可用來確定線程上下文的關於線程的信息。這些信息用於重建線程的環境。令對等線程相互之間產生區別的是id、定義線程狀態的寄存器組、優先級和它的棧。這些屬性使得線程有了自己的身份。

POSIX線程庫定義了線程屬性對象(attribute objec),它封裝了線程屬性的一個子集。這些屬性可以被線程的創建者訪問和更改。下面是可以被更改的線程屬性:

1)競爭範圍

2)棧大小

3)棧地址

4)分離的狀態

5)優先級

6)調度策略和參數

線程屬性對象可以同一個或多個線程關聯。屬性對象時定義了一個或一組線程的行為的概要(profile)。一旦對象被創建並初始化,可以在對線程創建函數的調用中重復引用它。如果重復使用,便會創建一組有著相同屬性的線程。所有使用該屬性對象的線程繼承所有的屬性值。一旦使用線程屬性對象創建了線程,多數屬性就不能夠在線程使用中改動。

範圍屬性描述了哪些線程同特定線程競爭資源。線程在兩個競爭範圍內爭奪資源:

1)進程範圍

2)系統範圍

線程依照競爭範圍和分配域(它被指派到的處理器集)來同其他線程競爭處理器的使用。有著進程競爭範圍的線程同進程中其他線程競爭,而有著系統競爭範圍的線程同系統分配的其他進程的線程競爭資源。有著系統範圍的線程和系統中所有線程一起被排序和調度。

線程的棧大小和位置是在線程被創建時設置的。如果線程棧的大小和位置沒有在創建期間指定,則系統會賦給它默認的大小和位置。默認大小同系統相關,是由進程所允許的線程的最大數目、進程地址空間的指定大小、系統資源使用的空間等決定的。線程的棧大小必須足夠大,以滿足任何函數調用、線程調用的進程外部代碼(如庫代碼)、局部變量存儲的需要。有著多個線程的進程應當有足以滿足其他所有線程棧的棧段。分配給進程的地址空間限制了棧的大小,從而限制了每個線程棧的大小。線程棧地址對於訪問有著不同屬性的內存區域的應用程序,可能會很重要。當您指定棧的位置時,需要註意點是,線程要求多少空間以及確保該位置不會同其他對等線程的棧發生重疊。

分離的線程時那些已經從它們的創建者中分離出來的線程。它們在終止或退出時,不需要同其他對等線程或主線程進行同步。它們仍共享所屬進程的地址空間,但是由於它們是分離的,創建它們的進程或線程不能對它們進行控制。當線程終止時,線程的id和狀態由系統保存,默認情況下,一旦線程終止,該情況會通知給創建者,線程的id和狀態會返回給創建者。如果線程是分離的,則不會使用資源來保存狀態或線程id。這些資源立即可以被系統重用。如果線程的創建者不需要在繼續處理之前等待線程終止,後者如果線程不要求在終止時同其他對等線程進行任何類型的異步,那麽該線程可以成為一個分離的線程。

線程從進程繼承調度策略。線程有優先級,而且優先級最高的線程會在較低優先級的線程之前執行。通過對線程區分優先次序,系統中需要立即執行或響應的任務會被指定到處理器上並得到時間片。如果有著更高優先級的線程可以運行,則正在執行的線程會被搶占。線程的優先級可以被降低或提高。調度策略也決定了哪個線程會被指派到處理器上。可使用的策略有先進先出、輪詢等。通常,沒有必要在進程執行期間改變線程的調度屬性。如果進程環境發生變動,改變了時間約束,使得您需要改進進程的性能,則可能需要對調度進行改動。但是要考慮到改動應用程序中指定進程的調度屬性,可能會對應用程序的總體性能產生負面影響。

6.4 線程的結構

我們已經討論了進程以及線程同他所屬進程的關系。圖6-2顯示了包含多個線程的進程結構。進程通過上下文和屬性區別於系統中其他進程,線程也可以通過上下文和屬性區別於其他對等線程。進程有代碼段、數據段和棧段。線程同進程共享代碼段和棧段。進程的棧通常從內存的高地址開始,向下增長。線程棧以下一個線程棧的開始位置為編輯。可以看到,線程棧包含其局部變量。進程的全局變量位於數據段中。threadA和threadB的上下文包括線程id、狀態、優先級、處理器寄存器等。程序計數器指向代碼段中函數task1() 和 task2()中下一條可執行指令。棧指針指向它們各自的棧的頂部。線程屬性對象同一個線程或一組線程相關聯。在本例中,兩個線程使用相同的線程屬性。

技術分享圖片

6.4.1 線程狀態

線程是當前進程被調度執行時的執行單元。如果進程中只有一個線程,該線程是只拍到處理器內核的主線程。如果進程有著多個線程,而且對於該進程有多個處理器可用,那麽所有的線程都會被指派到處理器上。

當線程被調度到處理器內核上執行時,它會改變自身的狀態。線程狀態是指在任意指定時間所處的模式或情形。線程有著同第5章進程接收的狀態和轉換相同的狀態和轉換。

有4種常見的狀態:

1)可運行

2)運行(活動)

3)停止

4)休眠(阻塞)

存在如下的轉換:

1)搶占

2) 接到信號

3)分派

4)時間片用完

主線程可以決定整個進程的狀態。如果主線程時唯一的線程,則主線程的狀態同進程的狀態相同。如果主線程在休眠,進程也在休眠。如果主線程在運行,進程也在運行。對於有著多個線程的進程,只有進程中所有線程都處於休眠或停止狀態時,我們才能夠認為整個進程休眠或停止。另一方面,如果一個線程是活動的(可運行或運行),那麽進程會被認為是活動的。

6.4.2 調度和線程競爭範圍

線程有著兩種競爭範圍:

1)進程競爭

2)系統競爭

有著進程競爭範圍的線程與相同進程的其他線程進行競爭。這些是混合線程(用戶級和內核級線程),系統將創建內核級線程池,用戶級線程將映射到它們。這些內核級線程是非綁定的,可以映射到一個線程或多個線程。然後內核根據調度屬性將內核線程調度到處理器上。

有著系統競爭範圍的線程同系統範圍內進程的線程進行競爭。這個模型由每個內核級線程對應一個用戶級線程組成。用戶線程在線程的生命期內綁定到內核級線程上。內核線程單獨負責在一個或多個處理器上調度線程執行。這個模型使用線程的調度屬性,根據系統中所有線程來進行線程調度。線程的默認競爭範圍根據實現定義。例如,對於Solaris10,默認競爭範圍是進程,但是丟與Suse Linux 2.6.13,默認競爭範圍時系統範圍。事實上,對於Suse linux 2.36.13,根本不支持進程競爭範圍。

圖6-3顯示了進程和系統兩種線程競爭範圍的區別。在有8個內核的多核環境中,有2個進程。進程A有4個線程,進程B有2個線程。進程A的4個線程中的3個線程競爭範圍是進程範圍,一個線程的競爭範圍是系統範圍。進程B的兩個線程中,一個線程競爭範圍是進程範圍,一個線程的競爭範圍是系統範圍。進程A中有著進程範圍的線程競爭內核0和1,進程B中有著進程範圍的線程將使用內核2.進程A和B中系統範圍的線程競爭內核4和5.有著進程範圍的線程映射到線程池。進程A的線程池中有3個內核級線程,進程B的線程池中有兩個內核級線程。

技術分享圖片

競爭範圍可以對應用程序的性能產生潛在影響。進程調度模型潛在的為做出調度決策提供較低的開銷。因為只需要對一個進程中的線程進行調度。

線程詳細剖析(四)