天天看點

如何去了解Linux中程序,線程等概念

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

轉自: http://blog.csdn.net/flowerui/article/details/1726493

繼續閱讀