乙個程序實體對應乙個task_struct結構體,關於這個結構體後續的文章會有介紹,這裡我們只需要知道通過該結構體我們可以獲得該程序使用的所有資源資訊。
程序id顧名思義就是程序的id,乙個程序有四種型別的id,分別是:
乙個程序可能包含多個執行緒,組成乙個執行緒組,執行緒組內所有的執行緒的tgid都等於組長的pid。
多個程序可以組成乙個程序組,乙個程序組內所有程序的pgid都等於組長的pid。
sid:幾個程序組可以組成乙個會話組,會話組內所有的程序都有相同的sid。
linux的命名空間是一種資源隔離機制,我們拿pid來做說明。
上圖是3級namespace,上級和下級之間是父子關係。關於namespace有兩點十分關鍵:
各個namespace之間的是相互隔離的,也就是說pid可以重複。如上圖各個namespace都有pid為1的程序。
在下級namespace中建立的程序,在上級namespace中是可見的。如上圖在level2 namespace中建立了程序pid=1,該程序在level 1 namespace中被對映為pid=3的程序,在level0 namespace中被對映為pid=5的程序。
struct pid
;
以上是pid資料結構的定義,有三個成員很重要,下面依次解釋:
level:表示該程序處於第幾級namespace。
number:表示該程序對應的所有pid成員,比如上圖中,程序處於level2 namespace,則該程序有三個pid成員。
tasks[pid_type_max]:指向對應的task_struct結構體,以便根據pid找到對應的task_struct。
struct upid ;
為了進一步理清各個結構體之間的關係,我們假設如下場景:在level2 namespace建立了乙個程序a,程序a與程序b,c同屬於乙個程序組,程序a是組長。下面是各個結構體之間的關係圖:
根據task struct獲取pid
static inline struct pid *task_pid(struct task_struct *task)
根據task_struct獲取執行緒組的id
static inline struct pid *task_tgid(struct task_struct *task)
執行緒組id其實就是執行緒組組長的pid。
3. 根據task_struct獲取程序組的pgid
static inline struct pid *task_tgid(struct task_struct *task)
跟執行緒組組長的pgid一致。
4. 根據task_struct獲取會話組tpid
static inline struct pid *task_session(struct task_struct *task)
跟執行緒組組長的tgid一致。
5. 根據pid和namespace獲取區域性pid number
pid_t pid_nr_ns(struct pid *pid, struct pid_namespace *ns)
return nr;
}
首先判斷pid在該namespace中是否可見,即判斷ns的level是否小於pid的level。
然後遍歷pid中的upid成員,找出ns一致的upid。
分配pid
struct pid *alloc_pid(struct pid_namespace *ns)
pid->numbers[i].nr = nr;
pid->numbers[i].ns = tmp;
tmp = tmp->parent;
} if (unlikely(is_child_reaper(pid)))
get_pid_ns(ns);
atomic_set(&pid->count, 1);
for (type = 0; type < pidtype_max; ++type)
init_hlist_head(&pid->tasks[type]);
upid = pid->numbers + ns->level;
spin_lock_irq(&pidmap_lock);
if (!(ns->nr_hashed & pidns_hash_adding))
goto out_unlock;
for ( ; upid >= pid->numbers; --upid)
spin_unlock_irq(&pidmap_lock);
return pid;
out_unlock:
spin_unlock_irq(&pidmap_lock);
put_pid_ns(ns);
out_free:
while (++i <= ns->level)
free_pidmap(pid->numbers + i);
kmem_cache_free(ns->pid_cachep, pid);
return err_ptr(retval);
}
分配pid主要分兩步:
第一步是在當前namespace以及所有的父namespace中分配pid number,並將資訊存入upid。
第二部是將upid鏈結到pid_hash雜湊陣列上去。
根據pid number以及namespace找到pid
struct pid *find_pid_ns(int nr, struct pid_namespace *ns)
主要分三步:
第一步是根據pid number以及namespace索引到pid_hash陣列中的某乙個。
第二部是迴圈遍歷找到pid number以及namespace匹配的upid。
第三步是根據upid計算得到pid。
本文參考部落格:
Linux核心之程序管理
linux核心之程序管理 支援執行緒的計算機系統裡面,程序作為資源分配的基本單位而存在,執行緒作為排程的基本單位而存在.執行緒僅擁有必不可少的一些資源,如 一組暫存器,堆疊資訊等等和其他執行緒共享同乙個程序的所有資源.所以,在同乙個程序的執行緒切換時不需要大量的儲存和恢復工作,同時由於共享同乙個儲存...
Linux核心 程序管理
注 對linux系統來說,執行緒只是一種特殊的程序,linux不區分執行緒和程序 程序 處於執行期的程式 包含的資源 一 程序描述符及任務結構 程序存放在任務佇列 task list 的雙向迴圈鍊錶中 鍊錶中每一項型別均為task struct 程序描述符,也可表示為task t 該結構定義在inc...
Linux核心 程序管理
1 程序生命週期 某個程序通過系統呼叫fork,建立乙個用於執行程式的程序。生成此程序的程序稱為父程序,被生成的程序稱為子程序。子程序通過複製父程序的資料得以建立 父程序執行系統呼叫wait,等待子程序結束 子程序通過系統呼叫exec將程式讀取到記憶體並開始執行 當程式執行完畢後,子程序通過系統呼叫...