共計 5664 個字符,預計需要花費 15 分鐘才能閱讀完成。
丸趣 TV 小編今天帶大家了解 Linux 的命名空間如何理解,文中知識點介紹的非常詳細。覺得有幫助的朋友可以跟著丸趣 TV 小編一起瀏覽文章的內容,希望能夠幫助更多想解決這個問題的朋友找到問題的答案,下面跟著丸趣 TV 小編一起深入學習“Linux 的命名空間如何理解”的知識吧。
一、基本概念
??命名空間(Linux namespace)是 linux 內核針對實現容器虛擬化映入的一個特性。我們創建的每個容器都有自己的命名空間,運行在其中的應用都像是在獨立的操作系統中運行一樣,命名空間保證了容器之間互不影響。
??Linux 的命名空間機制提供了一種資源隔離的解決方案。PID,IPC,Network 等系統資源不再是全局性的,而是屬于特定的 Namespace。Namespace 是對全局系統資源的一種封裝隔離,使得處于不同 namespace 的進程擁有獨立的全局系統資源,改變一個 namespace 中的系統資源只會影響當前 namespace 里的進程,對其他 namespace 中的進程沒有影響。
??傳統上,在 Linux 以及其他衍生的 UNIX 變體中,許多資源是全局管理的。例如,系統中的所有進程按照慣例是通過 PID 標識的,這意味著內核必須管理一個全局的 PID 列表。而且,所有調用者通過 uname 系統調用返回的系統相關信息(包括系統名稱和有關內核的一些信息)都是相同的。用戶 ID 的管理方式類似,即各個用戶是通過一個全局唯一的 UID 號標識。
??全局 ID 使得內核可以有選擇地允許或拒絕某些特權。雖然 UID 為 0 的 root 用戶基本上允許做任何事,但其他用戶 ID 則會受到限制。例如 UID 為 n 的用戶,不允許殺死屬于用戶 m 的進程(m≠ n)。但這不能防止用戶看到彼此,即用戶 n 可以看到另一個用戶 m 也在計算機上活動。只要用戶只能操縱他們自己的進程,這就沒什么問題,因為沒有理由不允許用戶看到其他用戶的進程。
??但有些情況下,這種效果可能是不想要的。如果提供 Web 主機的供應商打算向用戶提供 Linux 計算機的全部訪問權限,包括 root 權限在內。傳統上,這需要為每個用戶準備一臺計算機,代價太高。使用 KVM 或 VMWare 提供的虛擬化環境是一種解決問題的方法,但資源分配做得不是非常好。計算機的各個用戶都需要一個獨立的內核,以及一份完全安裝好的配套的用戶層應用。
??命名空間提供了一種不同的解決方案,所需資源較少。在虛擬化的系統中,一臺物理計算機可以運行多個內核,可能是并行的多個不同的操作系統。而命名空間則只使用一個內核在一臺物理計算機上運作,前述的所有全局資源都通過命名空間抽象起來。這使得可以將一組進程放置到容器中,各個容器彼此隔離。隔離可以使容器的成員與其他容器毫無關系。但也可以通過允許容器進行一定的共享,來降低容器之間的分隔。例如,容器可以設置為使用自身的 PID 集合,但仍然與其他容器共享部分文件系統。
二、實現
??命名空間的實現需要兩個部分:每個子系統的命名空間結構,將此前所有的全局組件包裝到命名空間中;將給定進程關聯到所屬各個命名空間的機制。
??子系統此前的全局屬性現在封裝到命名空間中,每個進程關聯到一個選定的命名空間。每個可以感知命名空間的內核子系統都必須提供一個數據結構,將所有通過命名空間形式提供的對象集中起來。struct nsproxy 用于匯集指向特定于子系統的命名空間包裝器的指針。在文件 nsproxy.h 中有:
/*
* A structure to contain pointers to all per-process
* namespaces - fs (mount), uts, network, sysvipc, etc.
*
* The pid namespace is an exception -- it s accessed using
* task_active_pid_ns. The pid namespace here is the
* namespace that children will use.
*
* count is the number of tasks holding a reference.
* The count for each namespace, then, will be the number
* of nsproxies pointing to it, not the number of tasks.
*
* The nsproxy is shared by tasks which share all namespaces.
* As soon as a single namespace is cloned or unshared, the
* nsproxy is copied.
*/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_for_children;
struct net *net_ns;
struct time_namespace *time_ns;
struct time_namespace *time_ns_for_children;
struct cgroup_namespace *cgroup_ns;};
??當前內核的以下范圍可以感知到命名空間
??1、UTS 命名空間包含了運行內核的名稱、版本、底層體系結構類型等信息。UTS 是 UNIXTimesharing System 的簡稱。
??2、保存在 struct ipc_namespace 中的所有與進程間通信(IPC)有關的信息。
??3、已經裝載的文件系統的視圖,在 struct mnt_namespace 中給出。
??4、有關進程 ID 的信息,由 struct pid_namespace 提供。
??5、struct user_namespace 保存的用于限制每個用戶資源使用的信息。
??6、struct net_ns 包含所有網絡相關的命名空間參數。
??當我討論相應的子系統時,會介紹各個命名空間容器的內容。在由于在創建新進程時可使用 fork 建立一個新的命名空間,因此必須提供控制該行為的適當的標志。每個命名空間都有一個對應的標志,在 sched.h 文件內:
#define CLONE_NEWCGROUP 0x02000000 /* New cgroup namespace */
#define CLONE_NEWUTS 0x04000000 /* New utsname namespace */
#define CLONE_NEWIPC 0x08000000 /* New ipc namespace */
#define CLONE_NEWUSER 0x10000000 /* New user namespace */
#define CLONE_NEWPID 0x20000000 /* New pid namespace */
#define CLONE_NEWNET 0x40000000 /* New network namespace */
??不同類型的命名空間的作用:
??IPC:用于隔離進程間通訊所需的資源(System V IPC, POSIX message queues),PID 命名空間和 IPC 命名空間可以組合起來用,同一個 IPC 名字空間內的進程可以彼此看見,允許進行交互,不同空間進程無法交互
??Network:Network Namespace 為進程提供了一個完全獨立的網絡協議棧的視圖。包括網絡設備接口,IPv4 和 IPv6 協議棧,IP 路由表,防火墻規則,sockets 等等。一個 Network Namespace 提供了一份獨立的網絡環境,就跟一個獨立的系統一樣。
??Mount:每個進程都存在于一個 mount Namespace 里面,mount Namespace 為進程提供了一個文件層次視圖。如果不設定這個 flag,子進程和父進程將共享一個 mount Namespace,其后子進程調用 mount 或 umount 將會影響到所有該 Namespace 內的進程。如果子進程在一個獨立的 mount Namespace 里面,就可以調用 mount 或 umount 建立一份新的文件層次視圖。
??PID::linux 通過命名空間管理進程號,同一個進程,在不同的命名空間進程號不同!進程命名空間是一個父子結構,子空間對于父空間可見。
??User:用于隔離用戶
??UTS:用于隔離主機名
??每個進程都關聯到自身的命名空間視圖,在任務定義的結構體 task_struct 中有如下定義:
struct task_struct {.../* 命名空間 */struct nsproxy *nsproxy;...}
??因為使用了指針,多個進程可以共享一組子命名空間。這樣,修改給定的命名空間,對所有屬于該命名空間的進程都是可見的。
??init_nsproxy 定義了初始的全局命名空間,其中維護了指向各子系統初始的命名空間對象的指針。在 kernel/nsproxy.c 文件內有
struct nsproxy init_nsproxy = {.count = ATOMIC_INIT(1),
.uts_ns = init_uts_ns,#if defined(CONFIG_POSIX_MQUEUE) || defined(CONFIG_SYSVIPC)
.ipc_ns = init_ipc_ns,#endif
.mnt_ns = NULL,
.pid_ns_for_children = init_pid_ns,#ifdef CONFIG_NET
.net_ns = init_net,#endif#ifdef CONFIG_CGROUPS
.cgroup_ns = init_cgroup_ns,#endif#ifdef CONFIG_TIME_NS
.time_ns = init_time_ns,
.time_ns_for_children = init_time_ns,#endif};
三、UTS 命名空間
??UTS 命名空間幾乎不需要特別的處理,因為它只需要簡單量,沒有層次組織。所有相關信息都匯集到下列結構的一個實例中。在 utsname.h 文件內:
struct uts_namespace {
struct new_utsname name;
struct user_namespace *user_ns;
struct ucounts *ucounts;
struct ns_common ns;} __randomize_layout;
??uts_namespace 所提供的屬性信息本身包含在 struct new_utsname 中:
struct oldold_utsname {char sysname[9];
char nodename[9];
char release[9];
char version[9];
char machine[9];};#define __NEW_UTS_LEN 64struct old_utsname {char sysname[65];
char nodename[65];
char release[65];
char version[65];
char machine[65];};struct new_utsname {char sysname[__NEW_UTS_LEN + 1];
char nodename[__NEW_UTS_LEN + 1];
char release[__NEW_UTS_LEN + 1];
char version[__NEW_UTS_LEN + 1];
char machine[__NEW_UTS_LEN + 1];
char domainname[__NEW_UTS_LEN + 1];}
??各個字符串分別存儲了系統的名稱(Linux…)、內核發布版本、機器名,等等。使用 uname 工具可以取得這些屬性的當前值,也可以在 /proc/sys/kernel/ 中看到
z@z-virtual-machine:~$ cat /proc/sys/kernel/ostype
Linux
z@z-virtual-machine:~$ cat /proc/sys/kernel/osrelease5.3.0-40-generic
??初始設置保存在 init_uts_ns 中,在 init/version.c 文件內:
struct uts_namespace init_uts_ns = {.ns.count = REFCOUNT_INIT(2),
.name = {
.sysname = UTS_SYSNAME,
.nodename = UTS_NODENAME,
.release = UTS_RELEASE,
.version = UTS_VERSION,
.machine = UTS_MACHINE,
.domainname = UTS_DOMAINNAME,
.user_ns = init_user_ns,
.ns.inum = PROC_UTS_INIT_INO,#ifdef CONFIG_UTS_NS
.ns.ops = utsns_operations,#endif};
什么是 Linux 系統
Linux 是一種免費使用和自由傳播的類 UNIX 操作系統,是一個基于 POSIX 的多用戶、多任務、支持多線程和多 CPU 的操作系統,使用 Linux 能運行主要的 Unix 工具軟件、應用程序和網絡協議。
感謝大家的閱讀,以上就是“Linux 的命名空間如何理解”的全部內容了,學會的朋友趕緊操作起來吧。相信丸趣 TV 丸趣 TV 小編一定會給大家帶來更優質的文章。謝謝大家對丸趣 TV 網站的支持!