linux核心程序命名空間函式分析

2021-10-02 12:19:45 字數 4291 閱讀 6489

struct  pid 與 struct task_struct 都是全域性的(核心的),struct  pid 的 level 為最高的命名空間層次(全域性的命名空間層次為0),

task_struct.pid  為全域性的pid,find_get_pid(pid_t nr);nr  必須為全域性pid_t pid ,因為後續的namespace 是根據current 巨集變數尋找的全域性pid_namespace;

首先給出乙個總圖,其中紅線是結構描述,黑線是指向。其中程序a,b,c是乙個程序組的,a是組長程序,所以b和

c的task_struct

結構體中的

pid_link

成員的node

欄位就被鄰接到程序

a對應的

struct pid

中的tasks[1]。

struct upid

通過pid_hash

和pid

數值關聯了起來,這樣就可以通過

pid數值快速的找到所有命名空間的

upid

結構,numbers

是乙個struct pid

的最後乙個成員,利用可變陣列來表示這個

pid結構當前有多少個命名空間.

struct pid

是程序id

在核心結構的乙個表示。但有可能會出現多個

task_struct

例項共享同乙個程序

id,這就需要將所有共享程序id的

task_struct

都以一種方式和

struct pid

關聯起來,這裡就是

struct pid

結構中的

tasks陣列

pid->tasks[

type]

此圖可以看到第乙個pid(session group) struct pid.tasks[pidtype_pid] 只有乙個struct task_struct 指向,struct pid.tasks[pidtype_sid]有三個,所以可以根據struct pid 和 type 尋找struct task_struct, 而通過namespace 和 nr 可以找到struct pid;

namespace+nr –>struct pid-> struct task_struct

struct pid也可以通過struct hlist_head tasks[pidtype_max]自己作為程序tasks[pidtype_pid], 也就是a,但是在實際測試中,無法找到自己作為會話程序的會話其他程序,也無法找到作為組長程序時其它程序tasks[pidtype_pgid],也就是b或者c,。顯然可以使用type=pidtype_pid,其它兩種情況不能使用。實際測試中,idtype_pid可以通過,idtype_pgid未通過。pidtype_sid未測試

struct task_struct + pid_type -> struct pid;( find_pid_ns函式)

struct pid[numbers] + pid_namespace.level ->upid->nr

task_struct  可以通過pid_link[pidtype_max] 找到組長程序

pid_link[pidtype_pgid],比如通過b的task_struct, pidtype_pgid找到a,自己作為程序pid_link [pidtype_pid], 也就是a,自己作為會話程序的會話其他程序。實際測試中,pidtype_pgid,idtype_pid可以通過,idtype_ssid

未通過。pidtype_sid未測試

組長程序tasks[pidtype_pid] == tasks[pidtype_pgid],

__task_pid_nr_ns(),引數task_struct(b), pidtype_pgid ==引數task_struct(a), pidtype_pid==引數task_struct(a), pidtype_pgid

第乙個等於是因為if (type != pidtype_pid) task = task->group_leader;

第二個等於是因為組長程序tasks[pidtype_pid] == tasks[pidtype_pgid]。

pid_t __task_pid_nr_ns(struct task_struct *task, enum pid_type type,

struct pid_namespace *ns)

task_struct 找自己在全域性的pid,然後通過指向的pid 和命名空間level,找到在命名空間pid(upid->nr)的區域性pid.  將

struct upid

按數字pid

和命名空間對映儲存,當給定數字

pid和命名空間時,可以獲取

struct upid

,然後根據

container_of

獲取struct pid

。struct pid

中的tasks

欄位的第乙個

task_struct。

pid_t pid_nr_ns(struct pid *pid, struct pid_namespace *ns)

struct pid_link pids[pidtype_max];

enum pid_type

;static inline structpid *task_pid(structtask_struct *task)

為2.6.11核心,3.19核心pid_hash沒有 0, 1, 2, 3也就是pid,pgid,sid,tgid.相當於只有乙個pid.《深入理解linux核心》第三版使用的時2.6.11,而《linux核心完全參考手冊》第二是3.19

struct pid *find_pid_ns(int nr, struct pid_namespace *ns)

find_pid_ns()

在pid_hash的雜湊表中根據雜湊函式得到pid所在的鍊錶頭部,然後遍歷得到 id 和 ns 都匹對的pid結構體指標;

void __init pidhash_init(void)

從pidhash_init函式中可以看出,pid_hash至少含有16項,最多4096項,它是系統中所有程序的雜湊表,根據id分配,但此雜湊表與pgid,tgid並無直接關係;

#define get_current()     (current_thread_info()->task)

#define current        get_current()

find_get_pid()

函式用於通過全域性

pid和其型別找到對應的

task

結構,find_get_pid(current->pid);current

為全域性struct task_struct.

task->pid

為全域性。

find_get_pid()

的引數必須為全域性

task

的pid_t pid. (task->pids[pidtype_pid].pid 也是全域性,pid_namespace.nr 不是全域性)

find_get_pid呼叫struct pid_namespace *task_active_pid_ns(struct task_struct *tsk)

task_active_pid_ns根據形參task獲得對應的pid namespace

其使用的例程如下:      

static int acct_on(struct filename *pathname)

本例中就根據當前task current 獲得current對應的pid namespace

其原始碼分析如下:

struct pid_namespace *task_active_pid_ns(struct task_struct *tsk)

可以看到這個函式分為兩步,第一步通過task_pid 拿到當前task的pid,這裡的pid是全域性的。

在已pid 為形參通過ns_of_pid 得到pid 對應的namespace

這裡為什麼說task_pid拿到pid是全域性的呢?

static inline struct pid *task_pid(struct task_struct *task)

可以看到這裡的pid是儲存在task中的pids 這個成員陣列中,根本和namespace不屬於任何的命令空間

而屬於系統啟動期間開始的init程序,即初始的命名空間。屬於task本身的資料結構。因此說task_pid得到的pid是全域性的。

PHP核心 命名空間

在維基百科中,對命名空間的定義是 命名空間 英語 namespace 表示識別符號 identifier 的上下文 context 乙個識別符號可在多個命名空間中定義,它在不同命名空間中的含義是互不相干的。在程式語言中,命名空間是一種特殊的作用域,它包含了處於該作用域內的識別符號,且本身也用乙個識別...

Linux核心之程序位址空間

程序使用的是虛擬記憶體中的位址,也叫線性位址,由作業系統協助相關硬體 如mmu 對映到實體地址。線性位址是通過頁表 page table 對映到物理記憶體,頁表由作業系統維護並被處理器引用。核心空間在頁表中擁有較高特權級,因此使用者態程式試圖訪問這些頁時會導致乙個頁錯誤。在linux中,核心空間是持...

Linux核心之程序位址空間

核心是作業系統中優先順序最高的成分 核心信任自己 核心總是盡量推遲給使用者態程序分配動態記憶體 核心必須能隨時準備捕獲使用者態程序引起的所有定址錯誤 當使用者態程序請求動態記憶體時,並沒有會的請求頁框,而僅僅獲得對乙個新的線性位址區間的使用權,而這一線性位址區間就稱為程序位址空間的一部分,這一區間叫...