歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux綜合 >> Linux資訊 >> Linux文化

如何去理解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

Copyright © Linux教程網 All Rights Reserved