Linux 內核使用 task_struct
數據結構來關聯所有與進程有關的數據和結構,Linux 內核所有涉及到進程和程序的所有算法都是圍繞該數據結構建立的,是內核中最重要的數據結構之一。該數據結構在內核文件 include/linux/sched.h
中定義,在Linux 3.8 的內核中,該數據結構足足有 380 行之多,在這裡我不可能逐項去描述其表示的含義,本篇文章只關注該數據結構如何來組織和管理進程ID的。
要想了解內核如何來組織和管理進程ID,先要知道進程ID的類型:
命名空間是為操作系統層面的虛擬化機制提供支撐,目前實現的有六種不同的命名空間,分別為mount命名空間、UTS命名空間、IPC命名空間、用戶命名空間、PID命名空間、網絡命名空間。命名空間簡單來說提供的是對全局資源的一種抽象,將資源放到不同的容器中(不同的命名空間),各容器彼此隔離。命名空間有的還有層次關系,如PID命名空間,圖1 為命名空間的層次關系圖。
圖1 命名空間的層次關系
在上圖有四個命名空間,一個父命名空間衍生了兩個子命名空間,其中的一個子命名空間又衍生了一個子命名空間。以PID命名空間為例,由於各個命名空間彼此隔離,所以每個命名空間都可以有 PID 號為 1 的進程;但又由於命名空間的層次性,父命名空間是知道子命名空間的存在,因此子命名空間要映射到父命名空間中去,因此上圖中 level 1 中兩個子命名空間的六個進程分別映射到其父命名空間的PID 號5~10。
命名空間增大了 PID 管理的復雜性,對於某些進程可能有多個PID——在其自身命名空間的PID以及其父命名空間的PID,凡能看到該進程的命名空間都會為其分配一個PID。因此就有:
Linux 內核在設計管理ID的數據結構時,要充分考慮以下因素:
如果將所有因素考慮到一起,將會很復雜,下面將會由簡到繁設計該結構。
如果先不考慮進程之間的關系,不考慮命名空間,僅僅是一個PID號對應一個task_struct,那麼我們可以設計這樣的數據結構:
struct task_struct { //... struct pid_link pids; //... }; struct pid_link { struct hlist_node node; struct pid *pid; }; struct pid { struct hlist_head tasks; //指回 pid_link 的 node int nr; //PID struct hlist_node pid_chain; //pid hash 散列表結點 };
每個進程的 task_struct 結構體中有一個指向 pid 結構體的指針,pid 結構體包含了 PID 號。結構示意圖如圖2。
圖2 一個task_struct對應一個PID
圖中還有兩個結構上面未提及:
至於上面的第1個問題就更加簡單,已知 task_struct 結構體,根據其 pid_link 的 pid 指針找到 pid 結構體,取出其 nr 即為 PID 號。
更多詳情見請繼續閱讀下一頁的精彩內容: http://www.linuxidc.com/Linux/2014-12/110233p2.htm