丝袜人妻一区二区三区_少妇福利无码视频_亚洲理论片在线观看_一级毛片国产A级片

【#NAME?】容器原理之 - namespace

Namespace簡(jiǎn)介

NEMESS(命名空間)是Linux提供的內(nèi)核級(jí)環(huán)境隔離方法,許多編程語(yǔ)言也有namespace等功能,如C、Java等。編程語(yǔ)言的namespace旨在允許在項(xiàng)目中的不同命名空間中使用相同的函數(shù)名或類名。

而Linux的 namespace 也是為了實(shí)現(xiàn)資源能夠在不同的命名空間里有相同的名稱,譬如在 A命名空間 有個(gè)pid為1的進(jìn)程,而在 B命名空間 中也可以有一個(gè)pid為1的進(jìn)程。

有了 namespace 就可以實(shí)現(xiàn)基本的容器功能,著名的 Docker 也是使用了 namespace 來(lái)實(shí)現(xiàn)資源隔離的。

Linux支持6種資源的 namespace,分別為(文檔):

在調(diào)用 clone() 系統(tǒng)調(diào)用時(shí),傳入以上的不同類型的參數(shù)就可以實(shí)現(xiàn)復(fù)制不同類型的namespace。比如傳入 CLONE_NEWPID參數(shù)時(shí),就是復(fù)制 pid命名空間,在新的 pid命名空間 里可以使用與其他 pid命名空間 相同的pid。代碼如下:

#define _GNU_SOURCE #include <; #include <; #include <uni; #include <sy; #include <sy; #include <; #include <; #include <errno.h> char child_stack[5000]; int child(void* arg) { printf("Child - %d\n", getpid()); return 1; } int main() { printf("Parent - fork child\n"); int pid = clone(child, child_stack+5000, CLONE_NEWPID, NULL); if (pid == -1) { perror("clone:"); exit(1); } waitpid(pid, NULL, 0); printf("Parent - child(%d) exit\n", pid); return 0; }

輸出如下:

Parent - fork child Parent - child(9054) exit Child - 1

從運(yùn)行結(jié)果可以看出,在子進(jìn)程的 pid命名空間 里當(dāng)前進(jìn)程的pid為1,但在父進(jìn)程的 pid命名空間 中子進(jìn)程的pid卻是9045。

namespace實(shí)現(xiàn)原理

為了讓每個(gè)進(jìn)程都可以從屬于某一個(gè)namespace,Linux內(nèi)核為進(jìn)程描述符添加了一個(gè) struct nsproxy 的結(jié)構(gòu),如下:

struct task_struct { ... /* namespaces */ struct nsproxy *nsproxy; ... } struct nsproxy { atomic_t count; struct uts_namespace *uts_ns; struct ipc_namespace *ipc_ns; struct mnt_namespace *mnt_ns; struct pid_namespace *pid_ns; struct user_namespace *user_ns; struct net *net_ns; };

從 struct nsproxy 結(jié)構(gòu)的定義可以看出,Linux為每種不同類型的資源定義了不同的命名空間結(jié)構(gòu)體進(jìn)行管理。比如對(duì)于 pid命名空間 定義了 struct pid_namespace 結(jié)構(gòu)來(lái)管理 。由于 namespace 涉及的資源種類比較多,所以本文主要以 pid命名空間 作為分析的對(duì)象。

我們先來(lái)看看管理 pid命名空間 的 struct pid_namespace 結(jié)構(gòu)的定義:

struct pid_namespace { struct kref kref; struct pidmap pidmap[PIDMAP_ENTRIES]; int last_pid; struct task_struct *child_reaper; struct kmem_cache *pid_cachep; unsigned int level; struct pid_namespace *parent; #ifdef CONFIG_PROC_FS struct vfsmount *proc_mnt; #endif };

因?yàn)?struct pid_namespace 結(jié)構(gòu)主要用于為當(dāng)前 pid命名空間 分配空閑的pid,所以定義比較簡(jiǎn)單:

  • kref 成員是一個(gè)引用計(jì)數(shù)器,用于記錄引用這個(gè)結(jié)構(gòu)的進(jìn)程數(shù)
  • pidmap 成員用于快速找到可用pid的位圖
  • last_pid 成員是記錄最后一個(gè)可用的pid
  • level 成員記錄當(dāng)前 pid命名空間 所在的層次
  • parent 成員記錄當(dāng)前 pid命名空間 的父命名空間

由于 pid命名空間 是分層的,也就是說(shuō)新創(chuàng)建一個(gè) pid命名空間 時(shí)會(huì)記錄父級(jí) pid命名空間 到 parent 字段中,所以隨著 pid命名空間 的創(chuàng)建,在內(nèi)核中會(huì)形成一顆 pid命名空間 的樹(shù),如下圖(圖片來(lái)源):

第0層的 pid命名空間 是 init 進(jìn)程所在的命名空間。如果一個(gè)進(jìn)程所在的 pid命名空間 為 N,那么其在 0 ~ N 層pid命名空間 都有一個(gè)唯一的pid號(hào)。也就是說(shuō) 高層pid命名空間 的進(jìn)程對(duì) 低層pid命名空間 的進(jìn)程是可見(jiàn)的,但是 低層pid命名空間的進(jìn)程對(duì) 高層pid命名空間 的進(jìn)程是不可見(jiàn)的。

由于在 第N層pid命名空間 的進(jìn)程其在 0 ~ N層pid命名空間 都有一個(gè)唯一的pid號(hào),所以在進(jìn)程描述符中通過(guò) pids 成員來(lái)記錄其在每個(gè)層的pid號(hào),代碼如下:

struct task_struct { ... struct pid_link pids[PIDTYPE_MAX]; ... } enum pid_type { PIDTYPE_PID, PIDTYPE_PGID, PIDTYPE_SID, PIDTYPE_MAX }; struct upid { int nr; struct pid_namespace *ns; struct hlist_node pid_chain; }; struct pid { atomic_t count; struct hlist_head tasks[PIDTYPE_MAX]; struct rcu_head rcu; unsigned int level; struct upid numbers[1]; }; struct pid_link { struct hlist_node node; struct pid *pid; };

這幾個(gè)結(jié)構(gòu)的關(guān)系如下圖:

我們主要關(guān)注 struct pid 這個(gè)結(jié)構(gòu),struct pid 有個(gè)類型為 struct upid 的成員 numbers,其定義為只有一個(gè)元素的數(shù)組,但是其實(shí)是一個(gè)動(dòng)態(tài)的數(shù)據(jù),它的元素個(gè)數(shù)與 level 的值一致,也就是說(shuō)當(dāng) level 的值為5時(shí),那么 numbers 成員就是一個(gè)擁有5個(gè)元素的數(shù)組。而每個(gè)元素記錄了其在每層 pid命名空間 的pid號(hào),而 struct upid 結(jié)構(gòu)的 nr 成員就是用于記錄進(jìn)程在不同層級(jí) pid命名空間 的pid號(hào)。

我們通過(guò)代碼來(lái)看看怎么為進(jìn)程分配pid號(hào)的,在內(nèi)核中是用過(guò) alloc_pid() 函數(shù)分配pid號(hào)的,代碼如下:

struct pid *alloc_pid(struct pid_namespace *ns) { struct pid *pid; enum pid_type type; int i, nr; struct pid_namespace *tmp; struct upid *upid; pid = kmem_cache_alloc(ns->pid_cachep, GFP_KERNEL); if (!pid) goto out; tmp = ns; for (i = ns->level; i >= 0; i--) { nr = alloc_pidmap(tmp); // 為當(dāng)前進(jìn)程所在的不同層級(jí)pid命名空間分配一個(gè)pid if (nr < 0) goto out_free; pid->numbers[i].nr = nr; // 對(duì)應(yīng)i層namespace中的pid數(shù)字 pid->numbers[i].ns = tmp; // 對(duì)應(yīng)i層namespace的實(shí)體 tmp = tmp->parent; } get_pid_ns(ns); pid->level = ns->level; atomic_set(&pid->count, 1); for (type = 0; type < PIDTYPE_MAX; ++type) INIT_HLIST_HEAD(&pid->tasks[type]); spin_lock_irq(&pidmap_lock); for (i = ns->level; i >= 0; i--) { upid = &pid->numbers[i]; // 把upid連接到全局pid中, 用于快速查找pid hlist_add_head_rcu(&upid->pid_chain, &pid_hash[pid_hashfn(upid->nr, upid->ns)]); } spin_unlock_irq(&pidmap_lock); out: return pid; ... }

上面的代碼中,那個(gè) for (i = ns->level; i >= 0; i--) 就是通過(guò) parent 成員不斷向上檢索為不同層級(jí)的 pid命名空間分配一個(gè)唯一的pid號(hào),并且保存到對(duì)應(yīng)的 nr 字段中。另外,還會(huì)把進(jìn)程所在各個(gè)層級(jí)的pid號(hào)添加到全局pid哈希表中,這樣做是為了通過(guò)pid號(hào)快速找到進(jìn)程。

現(xiàn)在我們來(lái)看看怎么通過(guò)pid號(hào)快速找到一個(gè)進(jìn)程,在內(nèi)核中 find_get_pid() 函數(shù)用來(lái)通過(guò)pid號(hào)查找對(duì)應(yīng)的 struct pid結(jié)構(gòu),代碼如下(find_get_pid() -> find_vpid() -> find_pid_ns()):

struct pid *find_get_pid(pid_t nr) { struct pid *pid; rcu_read_lock(); pid = get_pid(find_vpid(nr)); rcu_read_unlock(); return pid; } struct pid *find_vpid(int nr) { return find_pid_ns(nr, current->nsproxy->pid_ns); } struct pid *find_pid_ns(int nr, struct pid_namespace *ns) { struct hlist_node *elem; struct upid *pnr; hlist_for_each_entry_rcu(pnr, elem, &pid_hash[pid_hashfn(nr, ns)], pid_chain) if (pnr->nr == nr && pnr->ns == ns) return container_of(pnr, struct pid, numbers[ns->level]); return NULL; }

通過(guò)pid號(hào)查找 struct pid 結(jié)構(gòu)時(shí),首先會(huì)把進(jìn)程pid號(hào)和當(dāng)前進(jìn)程的 pid命名空間 傳入到 find_pid_ns() 函數(shù),而在 find_pid_ns() 函數(shù)中通過(guò)全局pid哈希表來(lái)快速查找對(duì)應(yīng)的 struct pid 結(jié)構(gòu)。獲取到 struct pid 結(jié)構(gòu)后就可以很容易地獲取到進(jìn)程對(duì)應(yīng)的進(jìn)程描述符,例如可以通過(guò) pid_task() 函數(shù)來(lái)獲取 struct pid 結(jié)構(gòu)對(duì)應(yīng)進(jìn)程描述符,由于代碼比較簡(jiǎn)單,這里就不再分析了。

1.《【#NAME?】容器原理之 - namespace》援引自互聯(lián)網(wǎng),旨在傳遞更多網(wǎng)絡(luò)信息知識(shí),僅代表作者本人觀點(diǎn),與本網(wǎng)站無(wú)關(guān),侵刪請(qǐng)聯(lián)系頁(yè)腳下方聯(lián)系方式。

2.《【#NAME?】容器原理之 - namespace》僅供讀者參考,本網(wǎng)站未對(duì)該內(nèi)容進(jìn)行證實(shí),對(duì)其原創(chuàng)性、真實(shí)性、完整性、及時(shí)性不作任何保證。

3.文章轉(zhuǎn)載時(shí)請(qǐng)保留本站內(nèi)容來(lái)源地址,http://f99ss.com/jiaoyu/2101295.html

上一篇

中班10以內(nèi)的減法教案看這里!把童年還給孩子!當(dāng)“雙減”拉下急剎車 義務(wù)教育如何做到“減”向均衡?

下一篇

關(guān)于中班2的減法教案我想說(shuō)"1元10節(jié)課“和”2萬(wàn)元一年" 學(xué)前兒童該上什么課?

【#NAME?】Excel公式中常見(jiàn)的錯(cuò)誤值

【#NAME?】Excel公式中常見(jiàn)的錯(cuò)誤值

#NAME?相關(guān)介紹,使用Exce電子表格的人可能會(huì)遇到各種問(wèn)題,經(jīng)常會(huì)發(fā)現(xiàn)表單中有錯(cuò)誤的值的信息。 比如#N/A!、#VALUE!、#DIV/0!等等。這都代表了什么信息呢?出現(xiàn)這些錯(cuò)誤該如何解決呢? 下面就介紹幾種ex...

#NAME?看這里!Python 的特殊變量 __name__

#NAME?看這里!Python 的特殊變量 __name__

#NAME?相關(guān)介紹,您可以在許多python代碼中看到__name__變量。 對(duì)于 Python 的初次使用用戶來(lái)說(shuō)可能對(duì)這個(gè)變量不是非常熟悉。 這樣理解就好了,__name__ 這個(gè)變量就是一個(gè)標(biāo)識(shí) Python 程序...

關(guān)于#NAME?我想說(shuō)Excel出現(xiàn)“NAME”提示怎么辦 如何解決Excel“NAME”提示

關(guān)于#NAME?我想說(shuō)Excel出現(xiàn)“NAME”提示怎么辦 如何解決Excel“NAME”提示

#NAME?相關(guān)介紹,使用Excel時(shí)出現(xiàn)“#NAME”錯(cuò)誤消息提示。 這通常是因?yàn)槭褂昧斯綗o(wú)法識(shí)別的文本。 解決這種情況,選擇“插入”→“名稱”→“定義”,打開(kāi)“定義名稱”。如果列舉的沒(méi)有所需要的名稱,可以在“在當(dāng)前工...

#NAME?,干貨看這篇!「Python」__name__ 是什么?

#NAME?,干貨看這篇!「Python」__name__ 是什么?

#NAME?相關(guān)介紹,前言 在我們?yōu)g覽一下 python 文件或者自己寫 python 代碼的時(shí)候,時(shí)常會(huì)在代碼的最后加上這樣的一行代碼 if __name__ == &#39;__main__&#39;: func_na...

#NAME??我來(lái)告訴你答案Excel中“NAME?”二三事

#NAME??我來(lái)告訴你答案Excel中“NAME?”二三事

#NAME?相關(guān)介紹,通常出現(xiàn)#NAME?符號(hào)的意思是出現(xiàn)了excel不能識(shí)別的東西,比如輸入錯(cuò)誤的公式、沒(méi)有加引號(hào)的文本等等。 達(dá)到當(dāng)天最大量API KEY 超過(guò)次數(shù)限制 用Excel篩選一列,這類里面出現(xiàn)了#NAME?...

#NAME??我來(lái)告訴你答案Excel出現(xiàn)“NAME”提示怎么辦 如何解決Excel“NAME”提示

#NAME??我來(lái)告訴你答案Excel出現(xiàn)“NAME”提示怎么辦 如何解決Excel“NAME”提示

#NAME?相關(guān)介紹,在使用Excel的過(guò)程中,出現(xiàn)了“#NAME”的錯(cuò)誤信息提示。 這種情況一般是由于在公式使用了無(wú)法識(shí)別的文本。 達(dá)到當(dāng)天最大量API KEY 超過(guò)次數(shù)限制解決這種情況,選擇“插入”→“名稱”→“定義”...

#NAME??終于找到答案了Excel中“NAME?”二三事

#NAME??終于找到答案了Excel中“NAME?”二三事

#NAME?相關(guān)介紹,通常會(huì)出現(xiàn)#NAME嗎?符號(hào)表示excel無(wú)法識(shí)別的輸入錯(cuò)誤公式、沒(méi)有引號(hào)的文本等。 用Excel篩選一列,這類里面出現(xiàn)了#NAME?,如下 進(jìn)行篩選,篩選#NAME?, 篩選的結(jié)果: 直接篩選是篩選...

#NAME?看這里!Excel公式中常見(jiàn)的錯(cuò)誤值

#NAME?看這里!Excel公式中常見(jiàn)的錯(cuò)誤值

#NAME?相關(guān)介紹,使用Exce電子表格的人可能會(huì)遇到各種問(wèn)題,經(jīng)常會(huì)發(fā)現(xiàn)表單中有錯(cuò)誤的值的信息。 比如#N/A!、#VALUE!、#DIV/0!等等。這都代表了什么信息呢?出現(xiàn)這些錯(cuò)誤該如何解決呢? 下面就介紹幾種ex...