Linux的命名空間詳解--Linux進程的管理與調度(二)【轉】

来源:https://www.cnblogs.com/linhaostudy/archive/2018/09/01/9570364.html
-Advertisement-
Play Games

Linux Namespaces機制提供一種資源隔離方案。 PID,IPC,Network等系統資源不再是全局性的,而是屬於特定的Namespace。每個Namespace裡面的資源對其他Namespace都是透明的。 要創建新的Namespace,只需要在調用clone時指定相應的flag。 Li ...


Linux Namespaces機制提供一種資源隔離方案。

PID,IPC,Network等系統資源不再是全局性的,而是屬於特定的Namespace。每個Namespace裡面的資源對其他Namespace都是透明的。要創建新的Namespace,只需要在調用clone時指定相應的flag。 Linux Namespaces機製為實現基於容器的虛擬化技術提供了很好的基礎,LXC(Linux containers)就是利用這一特性實現了資源的隔離。不同Container內的進程屬於不同的Namespace,彼此透明,互不幹擾。下麵我們就從clone系統調用的flag出發,來介紹各個Namespace。

命名空間提供了虛擬化的一種輕量級形式,使得我們可以從不同的方面來查看運行系統的全局屬性。該機制類似於Solaris中的zone或 FreeBSD中的jail。對該概念做一般概述之後,我將討論命名空間框架所提供的基礎設施。

命名空間概念

傳統上,在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集合,但仍然與其他容器共用部分文件系統。

本質上,命名空間建立了系統的不同視圖。此前的每一項全局資源都必須包裝到容器數據結構中,只有資源和包含資源的命名空間構成的二元組仍然是全局唯一的。雖然在給定容器內部資源是自足的,但無法提供在容器外部具有唯一性的ID。

考慮系統上有3個不同命名空間的情況。命名空間可以組織為層次,我會在這裡討論這種情況。一個命名空間是父命名空間,衍生了兩個子命名空間。假定容器用於虛擬主機配置中,其中的每個容器必須看起來像是單獨的一臺Linux電腦。因此其中每一個都有自身的init進程,PID為0,其他進程的PID 以遞增次序分配。兩個子命名空間都有PID為0的init進程,以及PID分別為2和3的兩個進程。由於相同的PID在系統中出現多次,PID號不是全局唯一的。

雖然子容器不瞭解系統中的其他容器,但父容器知道子命名空間的存在,也可以看到其中執行的所有進程。圖中子容器的進程映射到父容器中,PID為4到 9。儘管系統上有9個進程,但卻需要15個PID來表示,因為一個進程可以關聯到多個PID。至於哪個PID是”正確”的,則依賴於具體的上下文。

如果命名空間包含的是比較簡單的量,也可以是非層次的,例如下文討論的UTS命名空間。在這種情況下,父子命名空間之間沒有聯繫。

請註意,Linux系統對簡單形式的命名空間的支持已經有很長一段時間了,主要是chroot系統調用。該方法可以將進程限制到文件系統的某一部分,因而是一種簡單的命名空間機制。但真正的命名空間能夠控制的功能遠遠超過文件系統視圖。

Linux內核命名空間描述

在Linux內核中提供了多個namespace,其中包括fs (mount), uts, network, sysvipc, 等。一個進程可以屬於多個namesapce,既然namespace和進程相關,那麼在task_struct結構體中就會包含和namespace相關聯的變數。在task_struct 結構中有一個指向namespace結構體的指針nsproxy。

struct task_struct
{
……..
/* namespaces */
         struct nsproxy *nsproxy;
…….
}

再看一下nsproxy是如何定義的,在include/linux/nsproxy.h文件中,這裡一共定義了5個各自的命名空間結構體,在該結構體中定義了5個指向各個類型namespace的指針,由於多個進程可以使用同一個namespace,所以nsproxy可以共用使用,count欄位是該結構的引用計數。

/* '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;
};
  1. UTS命名空間包含了運行內核的名稱、版本、底層體繫結構類型等信息。UTS是UNIX Timesharing System的簡稱。
  2. 保存在struct ipc_namespace中的所有與進程間通信(IPC)有關的信息。
  3. 已經裝載的文件系統的視圖,在struct mnt_namespace中給出。
  4. 有關進程ID的信息,由struct pid_namespace提供。
  5. struct net_ns包含所有網路相關的命名空間參數。

系統中有一個預設的nsproxy,init_nsproxy,該結構在task初始化是也會被初始,定義在include/linux/init_task.h

#define INIT_TASK(tsk)  \
{
……..
         .nsproxy   = &init_nsproxy,      
……..
}

其中init_nsproxy的定義為:

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
};

對於.mnt_ns沒有進行初始化,其餘的namespace都進行了系統預設初始化;

命名空間的創建

新的命名空間可以用下麵兩種方法創建。

  1. 在用fork或clone系統調用創建新進程時,有特定的選項可以控制是與父進程共用命名空間,還是建立新的命名空間。
  2. unshare系統調用將進程的某些部分從父進程分離,其中也包括命名空間。更多信息請參見手冊頁unshare(2)。

在進程已經使用上述的兩種機制之一從父進程命名空間分離後,從該進程的角度來看,改變全局屬性不會傳播到父進程命名空間,而父進程的修改也不會傳播到子進 程,至少對於簡單的量是這樣。而對於文件系統來說,情況就比較複雜,其中的共用機制非常強大,帶來了大量的可能性。

命名空間的實現需要兩個部分:每個子系統的命名空間結構,將此前所有的全局組件包裝到命名空間中;將給定進程關聯到所屬各個命名空間的機制。

在用fork或clone系統調用創建新進程時,有特定的選項可以控制是與父進程共用命名空間,還是建立新的命名空間。這些選項如下:

  • CLONE_NEWPID 進程命名空間。空間內的PID 是獨立分配的,意思就是命名空間內的虛擬 PID 可能會與命名空間外的 PID 相衝突,於是命名空間內的 PID 映射到命名空間外時會使用另外一個 PID。比如說,命名空間內第一個 PID 為1,而在命名空間外就是該 PID 已被 init 進程所使用。
  • CLONE_NEWIPC 進程間通信(IPC)的命名空間,可以將 SystemV 的 IPC 和 POSIX 的消息隊列獨立出來。
  • CLONE_NEWNET 網路命名空間,用於隔離網路資源(/proc/net、IP 地址、網卡、路由等)。後臺進程可以運行在不同命名空間內的相同埠上,用戶還可以虛擬出一塊網卡。
  • CLONE_NEWNS 掛載命名空間,進程運行時可以將掛載點與系統分離,使用這個功能時,我們可以達到 chroot 的功能,而在安全性方面比 chroot 更高。
  • CLONE_NEWUTS UTS 命名空間,主要目的是獨立出主機名和網路信息服務(NIS)。
  • CLONE_NEWUSER 用戶命名空間,同進程 ID 一樣,用戶 ID 和組 ID 在命名空間內外是不一樣的,並且在不同命名空間內可以存在相同的 ID。

PID Namespace

當調用clone時,設定了CLONE_NEWPID,就會創建一個新的PID Namespace,clone出來的新進程將成為Namespace里的第一個進程。一個PID Namespace為進程提供了一個獨立的PID環境,PID Namespace內的PID將從1開始,在Namespace內調用fork,vfork或clone都將產生一個在該Namespace內獨立的PID。新創建的Namespace里的第一個進程在該Namespace內的PID將為1,就像一個獨立的系統里的init進程一樣。該Namespace內的孤兒進程都將以該進程為父進程,當該進程被結束時,該Namespace內所有的進程都會被結束。PID Namespace是層次性,新創建的Namespace將會是創建該Namespace的進程屬於的Namespace的子Namespace。子Namespace中的進程對於父Namespace是可見的,一個進程將擁有不止一個PID,而是在所在的Namespace以及所有直系祖先Namespace中都將有一個PID。系統啟動時,內核將創建一個預設的PID Namespace,該Namespace是所有以後創建的Namespace的祖先,因此系統所有的進程在該Namespace都是可見的。

IPC Namespace

當調用clone時,設定了CLONE_NEWIPC,就會創建一個新的IPC Namespace,clone出來的進程將成為Namespace里的第一個進程。一個IPC Namespace有一組System V IPC objects 標識符構成,這標識符有IPC相關的系統調用創建。在一個IPC Namespace裡面創建的IPC object對該Namespace內的所有進程可見,但是對其他Namespace不可見,這樣就使得不同Namespace之間的進程不能直接通信,就像是在不同的系統里一樣。當一個IPC Namespace被銷毀,該Namespace內的所有IPC object會被內核自動銷毀。

PID Namespace和IPC Namespace可以組合起來一起使用,只需在調用clone時,同時指定CLONE_NEWPIDCLONE_NEWIPC,這樣新創建的Namespace既是一個獨立的PID空間又是一個獨立的IPC空間。不同Namespace的進程彼此不可見,也不能互相通信,這樣就實現了進程間的隔離。

mount Namespace

當調用clone時,設定了CLONE_NEWNS,就會創建一個新的mount Namespace。每個進程都存在於一個mount Namespace裡面,mount Namespace為進程提供了一個文件層次視圖。如果不設定這個flag,子進程和父進程將共用一個mount Namespace,其後子進程調用mount或umount將會影響到所有該Namespace內的進程。如果子進程在一個獨立的mount Namespace裡面,就可以調用mount或umount建立一份新的文件層次視圖。該flag配合pivot_root系統調用,可以為進程創建一個獨立的目錄空間。

Network Namespace

當調用clone時,設定了CLONE_NEWNET,就會創建一個新的Network Namespace。一個Network Namespace為進程提供了一個完全獨立的網路協議棧的視圖。包括網路設備介面,IPv4和IPv6協議棧,IP路由表,防火牆規則,sockets等等。一個Network Namespace提供了一份獨立的網路環境,就跟一個獨立的系統一樣。一個物理設備只能存在於一個Network Namespace中,可以從一個Namespace移動另一個Namespace中。虛擬網路設備(virtual network device)提供了一種類似管道的抽象,可以在不同的Namespace之間建立隧道。利用虛擬化網路設備,可以建立到其他Namespace中的物理設備的橋接。當一個Network Namespace被銷毀時,物理設備會被自動移回init Network Namespace,即系統最開始的Namespace。

UTS Namespace

當調用clone時,設定了CLONE_NEWUTS,就會創建一個新的UTS Namespace。一個UTS Namespace就是一組被uname返回的標識符。新的UTS Namespace中的標識符通過複製調用進程所屬的Namespace的標識符來初始化。Clone出來的進程可以通過相關係統調用改變這些標識符,比如調用sethostname來改變該Namespace的hostname。這一改變對該Namespace內的所有進程可見。CLONE_NEWUTS和CLONE_NEWNET一起使用,可以虛擬出一個有獨立主機名和網路空間的環境,就跟網路上一臺獨立的主機一樣。

以上所有clone flag都可以一起使用,為進程提供了一個獨立的運行環境。LXC正是通過clone時設定這些flag,為進程創建一個有獨立PID,IPC,FS,Network,UTS空間的container。一個container就是一個虛擬的運行環境,對container里的進程是透明的,它會以為自己是直接在一個系統上運行的。一個container就像傳統虛擬化技術裡面的一臺安裝了OS的虛擬機,但是開銷更小,部署更為便捷。

Linux Namespaces機制本身就是為了實現 container based virtualizaiton開發的。它提供了一套輕量級、高效率的系統資源隔離方案,遠比傳統的虛擬化技術開銷小,不過它也不是完美的,它為內核的開髮帶來了更多的複雜性,它在隔離性和容錯性上跟傳統的虛擬化技術比也還有差距。

user_namespace

CLONE_NEWUSER指定子進程擁有新的用戶空間


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 一、字元串 通過string定義一個字元串,或者通過String類來創建對象。 通過new String() 創建有一下幾種構造函數(從元數據),以此順序創建string; // // 摘要: // 將 System.String 類的新實例初始化為由 Unicode 字元數組指示的值。 // // ...
  • 先新建一個過濾器ExceptionHandleErrorAttribute.cs 內容如下: 1 using System; 2 using System.Net; 3 using System.Web; 4 using System.Web.Mvc; 5 using ABBPMP.Utility. ...
  • Supervision,字面意思是監督,是父Actor發現子Actor有異常發生後,對子Actor產用保種策略處理的機制,如果父Actor不處理,則往上傳遞。 ...
  • touch 創建空文件(當然,你也可以使用echo >filename)ln 創建鏈接符號(快捷方式|引用):符號鏈接:ln –s硬鏈接:ln區別:符號鏈接產生了一個快捷方式,是對源文件的一個鏈接。硬鏈接是底層位元組的鏈接,簡單來說,相當於是一個文件,兩個文件名,占用同一塊扇區,好處是省空間,即便刪除... ...
  • 【原文】https://www.toutiao.com/i6593191234326495752/ 一、硬碟 硬碟最怕的是震動,大的震動會讓磁頭組件碰到碟片上,劃傷了可就壞大事了,修都不好修,最重要的是你的數據可就沒了——你的心血喲! 二、主板 主板最怕的是靜電和形變。靜電可能會弄壞BIOS晶元和數... ...
  • 一. Linux文件系統路徑說明 熟悉windows系統的,都知道文件路徑表示,如C:\User\rich\Documnets\test.doc。 在linux中目錄稱為虛擬目錄(virtual directory) 根目錄是root,根目錄下的目錄和文件會按照訪問它們的目錄路徑一一列出。如:/ho ...
  • FTP全名是File Transfer Protocol(文件傳輸協議) C/S架構 簡介: 下麵是關於FTP這個服務的屬性 (1)FTP服務相關軟體 IIS Serv-U Vsftpd proftpd pureftpd (2)FTP客戶端相關軟體 ftp命令 CuteFTP FlashFTP Le ...
  • 變數名 含義 ARGC 命令行變元個數 ARGV 命令行變元數組 FILENAME 當前輸入文件名 FNR 當前文件中的記錄號 FS 輸入域分隔符,預設為一個空格 RS 輸入記錄分隔符 NF 當前記錄里域個數 NR 到目前為止記錄數 OFS 輸出域分隔符 ORS 輸出記錄分隔符 1、awk '/10 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...