zt:理解Linux中程式,執行緒等概念

lfree發表於2006-08-30

1 基本概念

1.1. 程式和執行緒
可執行檔案由指令和資料組成。程式就是在計算機上執行的可執行檔案針對特定的輸入資料的一個例項,同一個可執行程式檔案如果操作不同的輸入資料就是兩個不同的程式。
線 程是程式的一條執行路徑,它包含獨立的堆疊和CPU暫存器狀態,每個執行緒共享其所附屬的程式的所有的資源,包括開啟的檔案、頁表(因此也就共享整個使用者態 地址空間)、訊號標識及動態分配的記憶體等等。執行緒和程式的關係是:執行緒是屬於程式的,執行緒執行在程式空間內,同一程式所產生的執行緒共享同一實體記憶體空間, 當程式退出時該程式所產生的執行緒都會被強制退出並清除。
Linux在核外採用1:1執行緒模型,即用一個核心程式(輕量程式)對應一個執行緒,將執行緒 排程等同於程式排程,交給核心完成,而其它諸如執行緒取消、執行緒間的同步等工作,都是在核外執行緒庫中完成的。因此可以把程式看作一組執行緒,這組執行緒擁有相同 的執行緒組號(TGID),這個TGID就是這組執行緒序所附屬的程式的ID號,每個執行緒的ID號就是我們用ps命令所看到的LWP號。
為了方便,從 現在起我們用任務來代替程式和執行緒,即每提到任務,我們就是指執行緒和程式,除非要強調執行緒和程式之間的不同之處。任務的週期從被fork開始一直到給任務 從程式表中消失。一個程式包括:正文段(text),資料段(data),棧段(STACK)和共享記憶體段(SHARED MEMORY)。

1.2. 中斷和訊號
(1)中斷
中 斷通常定義為用來改變CPU執行的指令的順序的事件。對於其分類可謂是仁者見仁,智者見智,但畢竟有勝於無,這裡給出一種分類:硬中斷、異常中斷和軟中 斷。硬中斷也稱為外部中斷,分為兩類,可遮蔽和不可遮蔽。/proc/interrupts列出了當前系統定義的所有硬中斷。
異常中斷是系統執行出現異常時候CPU自動產生的中斷,如除數為零、使用虛擬記憶體機制時的缺頁保護異常等。軟中斷是由程式指令中包含INT 指令產生的中斷,如單步跟棕;該中斷處理的一部分任務可以延遲一會再處理。

1.3. CPU 的狀態
CPU的狀態可分為有7種:
(1)常規使用者態(目態): CPU所執行的任務在訪問該任務自己的記憶體空間;
(2)核心態(管態):如果CPU正在執行核心程式或在CPU上執行的任務正在透過系統呼叫請求核心服務,例如訪問硬體,這時就稱CPU處於核心態;
(3)CPU執行nice任務,一個優先順序別低於普通任務的優先順序別的任務;
(4)io等待: 由於任務等待I/O而使CPU處於空閒狀態,這些I/O主要指block I/O,raw I/O,VM paging/swapins;
(5)閒置:系統中的所有任務由於等待除了I/O以外的事件的發生而處於睡眠狀態,或者系統沒有任務;
(6)CPU正在處理硬中斷,即 在irq狀態;
(7)CPU正在處理軟中斷。

從 使用者態轉換為核心態的唯一途徑是中斷。CPU處於使用者態時,所執行的程式只能執行非特權指令,如果使用者程式在使用者態下執行特權指令,將發生中斷,由操作系 統獲得控制。作業系統在核心態下執行。從核心態到使用者態可以透過修改程式狀態字來實現,這將伴隨這由作業系統程式到使用者程式的轉換。

1.4. 任務優先順序
每個任務在Kernel2.6 中不是由排程器統一計算,而是獨立計算。優先順序由兩部分構成:
(1)靜態優先順序。Nice是程式的靜態優先順序。靜態優先順序在任務建立的時候就被賦值,並且不變(除非用系統呼叫改變任務的nice值);
(2) 動態優先順序(task->counter-MAX_RT_PRIO)。它定義了一個在就緒佇列的程式當它得到CPU後可執行的時間。計算機是以時鐘 中斷作為時間的計數器,每傳送一個時鐘中斷,動態優先順序上的時間片就減少一個時鐘中斷的時間,時間片減到0的時候就退出該程式而執行另一個程式。任務的動 態優先順序則是跟靜態優先順序和平均等待時間(sleep_avg)有關。對於實時任務的優先順序在建立的時候就確定了,而且一旦確定以後就不再改變,所以下面 部分僅對於非實時任務而言,任務的平均等待時間越大,任務的動態優先順序也就越高。

有以下幾種情況需要計算任務的優先順序:
(1)建立新任務,使用函式effective_prio()(因為此時任務尚未進行排程,沒有sleep_avg和interactive_credit可言);
(2)喚醒等待任務時,使用函式recalc_task_prio ()來計算任務動態優先順序。
(3)任務用完時間片以後,被重新插入到active array或者expired array的時候需要
(4)其它情況,如IDLE任務初始化等時候。
動 態優先順序的計算公式為:PRI=NICE+40+CPU_ PENALTY,從公式中可以看到大多數使用者任務的優先順序是大於40的。可以使用“ps -l”和“ps -emo THREAD”命令分別查尋任務和執行緒的CPU使用狀態。使用“nice -n proname”和“renice +n proid”來修改任務的優先順序。nice值的系統缺值為20。
renice command. It uses the same priorities as nice, but is used on processes that are already running. It can take the -p option for a specific PID, the -g option for a process group, or -u for the processes belonging to a specific user.

1.5. CPU佇列長度
一個任務如果擁有了除CPU以外的所有執行時所需要的資源,我們就稱該任務為可執行任務。可執行任務包含等待佇列和正在CPU上執行的任務,這些任務構成了執行佇列。執行佇列長度為任務的個數,執行佇列越長,任務等待時間越長。
一個阻塞任務可能在等待I/O資料或等待一個系統呼叫的結果。當一個任務即將進入執行佇列時,核心首先計算其優先權,然後再放入相應的優先順序的執行佇列裡;在執行過程中,可執行的任務的優先順序每秒更新一次,因此其在可執行佇列的位置可動態調整。

1.6. 上下文切換的比率
CPU 一般在某一時刻只能執行一個任務。為了給使用者一個並行的感覺,Linux核心不停在各個任務之間切換,這個切換叫做上下文切換。上下文包括:CPU的所有 暫存器中的值、任務的狀態以及堆疊中的內容。上下文切換的主要任務是儲存老任務CPU狀態,並載入新任務的儲存狀態,用新任務的記憶體映像替換老任務的記憶體 映像。因此上下文切換導致大量資訊的轉移,導致了昂貴的上下文切換開銷。因此,要儘可能減少該切換。
要減少切換,必須知道切換如何發生。在下列情況下發生上下文切換:
 任務結束;
 任務使用完時間片,為使各個任務能公平地使用CPU,核心透過時間中斷來實現排程,不能的體系結構以及不同的核心,每秒時間中斷的次數不一樣;
 任務需要的資源當前不可用(如缺頁)或任務等待I/O操作的完成;
 當睡眠任務被喚醒進入可執行佇列時,如果該任務的優先順序高於所有可執行的任務而且正在執行的任務可被搶佔;
 任務利用訊號或系統呼叫自動放棄CPU;


1.7. 任務狀態

任務總共有6種狀態標誌,分別是:
(1)可執行狀態:可執行狀態是那些正在等待CPU資源的任務的狀態,這些任務在就緒佇列run-queqe中.這些任務只要得到CPU在個資源就馬上可以被執行
(2)可打斷睡眠狀態:處於等待佇列中的任務,待資源有效時喚醒,也可由其它任務被訊號中斷、喚醒後進入就緒狀態
(3)不可打斷睡眠狀態:處於等待佇列中的任務,直接等待硬體條件,待資源有效時喚醒,不可由其它任務透過訊號中斷、喚醒;這類狀態的任務其睡眠的時間相對比較短。與可打斷睡眠狀態的區別就是後者可以由訊號喚醒。
(4)僵死狀態:雖然此時已經釋放了記憶體、檔案等資源,但是還沒有釋放任務控制塊task_struct資料結構項。它不進行任何排程或狀態轉換,等待父任務將它徹底釋放
(5)暫停狀態:可能是任務控制訊號所致,或者正在被跟蹤除錯,而導致暫時停止執行;需要其它任務的訊號才能喚醒。任務被暫停,透過其它任務的訊號才能喚醒。正在除錯的任務可以在該停止狀態。
(6)TAS_DEAD:已經退出且不需要父任務回收的任務的狀態。
一個任務只能執行在使用者方式(CPU處於使用者態)或核心方式(CPU處於核心態)下。在使用者方式下任務使用一般的堆疊,而在核心方式下用的是固定大小的堆疊(一般為一個實體記憶體頁大小)。

1.8. 系統平均負載
系 統平均負載用來衡量系統工作量(服務的任務的數目)的指標。Linux系統採用指數衰減移動平均演算法來計算系統平均負載,即當前系統的負載=上次計算的負 載 衰減因子 + 這一時刻系統的任務數目*(1-衰減因子)。所用的任務種類包括執行佇列的任務和不可打斷睡眠狀態的任務。預設時,Linux系統提供1分鐘,分鐘和15 分鐘三種形式的系統平均負載,為方便,我們就稱之為1-分鐘平均負載、5-分鐘平均負載、15-分鐘平均負載。時間越短,衰減越快(衰減大),越能反映系 統的負載突變情況;時間越長,衰減越慢,能反映系統的平均情況。

1.9. 程式的capability

傳統UNIX的訪 問控制模型非常簡單,就是“超級使用者對普通使用者”模型。在這種模型中,一個程式或帳戶要麼什麼都能做即具有全部的系統許可權,要麼幾乎什麼也不能做即只有很 小的許可權,這取決於程式的UID。例如,如果一個程式需要載入/解除安裝核心模組以及管理檔案系統等操作時,就需要完全的root許可權。很顯然這樣做對系統安 全存在很大的威脅。UNIX系統中的SUID問題就是由這種信任狀模型造成的。例如,一個普通使用者需要使用ping命令。這是一個SUID命令,會以 root的許可權執行。而實際上這個程式只是需要載入/解除安裝核心模組,除此之外的其它 root的許可權對這個程式都是沒有必要的。如果程式編寫不好,就可能被攻擊者利用,獲得系統的控制權。
使用能力(capability)可以減小 這種風險。系統管理員為了系統的安全可以剝奪root使用者的某些能力,這樣即使root使用者也將無法進行某些操作;而這個過程又是不可逆的,也就是說如果 一種能力被刪除,除非重新啟動系統,否則即使root使用者也無法重新新增被刪除的能力。

當特權操作由Capability LSM 模組控制時,系統基於程式信任狀(creds)來仲裁特權操作。當Capability未被編譯進核心時,核心使用預設的安全模組 (security/dummy.c)仲裁特權操作,機制非常簡單,僅僅檢查程式euid、fsuid(進行檔案系統相關特權操作時)是否為0。在這種情 況下,dummy模組根本不關心程式的信任狀,每個程式的信任狀都複製其父程式的信任狀。追根溯源,每個程式的信任狀無論程式使用者是否為超級使用者,最終都 複製Init程式的信任狀,信任狀中包含有超級使用者程式的所有權能。
Linux是如何使用POSIX capabilities代替傳統的信任狀模型的?每個程式有三個和能力有關的點陣圖:inheritable(I)、permitted(P)和 effective(E),對應程式描述符 task_struct(include/linux/sched.h)裡面的cap_effective, cap_inheritable, cap_permitted。每種能力由一位表示,1表示具有某種能力,0表示沒有。
 cap_effective。當一個程式要進行某個特權操作時,作業系統會檢查 cap_effective的對應位是否有效,而不再是檢查程式的有效UID是否為0。例如,如果一個程式要設定系統的時鐘,Linux的核心就會檢查 cap_effective的CAP_SYS_TIME位(第25位)是否有效,
 cap_permitted表示程式能夠使用的能力。在cap_permitted中可以包含cap_effective中沒有的能力,這些能力是被程式 自己臨時放棄的,也可以說cap_effective是cap_permitted的一個子集。程式放棄沒有必要的能力對於提高安全性大有助益。例如, ping只需要CAP_NET_RAW,如果它放棄除這個能力之外的其它能力,即使存在安全缺陷,也不會對系統造成太大的損害。
 cap_inheritable表示能夠被當前程式執行的程式繼承的能力。

Linux實現了7個POSIX 1003.1e規定的能力,還有21個(截止到2.6.13版本的核心)Linux所特有的,這些能力在/usr/src/linux/include/linux/capability.h檔案中定義。其細節如下:

能力 編號 解釋
CAP_CHOWN 0 允許改變檔案的所有權
CAP_DAC_OVERRIDE 1 忽略對檔案的所有DAC訪問限制
CAP_DAC_READ_SEARCH 2 忽略所有對讀、搜尋操作的限制
CAP_FOWNER 3 如果檔案屬於程式的UID,就取消對檔案的限制
CAP_FSETID 4 允許設定setuid位
CAP_KILL 5 允許對不屬於自己的程式傳送訊號
CAP_SETGID 6 允許改變組ID
CAP_SETUID 7 允許改變使用者ID
CAP_SETPCAP 8 8 允許向其它程式轉移能力以及刪除其它程式的任意能力
CAP_LINUX_IMMUTABLE 9 允許修改檔案的不可修改(IMMUTABLE)和只新增(APPEND-ONLY)屬性
CAP_NET_BIND_SERVICE 10 允許繫結到小於1024的埠
CAP_NET_BROADCAST 11 允許網路廣播和多播訪問
CAP_NET_ADMIN 12 允許執行網路管理任務:介面、防火牆和路由等,詳情請參考/usr/src/linux/include/linux/capability.h檔案
CAP_NET_RAW 13 允許使用原始(raw)套接字
CAP_IPC_LOCK 14 允許鎖定共享記憶體片段
CAP_IPC_OWNER 15 忽略IPC所有權檢查
CAP_SYS_MODULE 16 插入和刪除核心模組
CAP_SYS_RAWIO 17 允許對ioperm/iopl的訪問
CAP_SYS_CHROOT 18 允許使用chroot()系統呼叫
CAP_SYS_PTRACE 19 允許跟蹤任何程式
CAP_SYS_PACCT 20 允許配置程式記帳(process accounting)
CAP_SYS_ADMIN 21 允許執行系統管理任務:載入/解除安裝檔案系統、設定磁碟配額、開/關交換裝置和檔案等。詳情請參考/usr/src/linux/include/linux/capability.h檔案。
CAP_SYS_BOOT 22 允許重新啟動系統
CAP_SYS_NICE 23 允許提升優先順序,設定其它程式的優先順序//
CAP_SYS_RESOURCE 24 忽略資源限制
CAP_SYS_TIME 25 允許改變系統時鐘
CAP_SYS_TTY_CONFIG 26 允許配置TTY裝置
CAP_MKNOD 27 允許使用mknod()系統呼叫
CAP_LEASE 28 Allow taking of leases on files

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/267265/viewspace-82906/,如需轉載,請註明出處,否則將追究法律責任。

相關文章