linux中的namespace


     本文將就namespace這個知識點,進行簡單的歸納總結,力求通俗易通。在資料匯總的過程中,參考了許多網上的博客資料,在文章尾部給出相關鏈接。

     namespace,命名空間,從名字上看,應該是類似於包含許多名字的空間,打個比方,三年一班的小明和三年二班的小明,雖說他們名字是一樣的,但是所在班級不一樣,那么,在全年級排行榜上面,即使出現兩個名字一樣的小明,也會通過各自的學號來區分。對於學校來說,每個班級就相當於是一個命名空間,這個空間的名稱是班級號。班級號用於描述邏輯上的學生分組信息,至於什么學生分配到1班,什么學生分配到2班,那就由學校層面來統一調度。大致應該就是這么個意思,恩。

C++中的命名空間

     命名空間這個概念不僅僅在kernel中有使用,在其他語言中也有所體現。例如在C++中,標准C++庫中所包含的所有內容(包括常量、變量、結構、類和函數)都被定義在命名空間std中。我們可以定義有名命名空間,也可以定義無名命名空間,命名空間可以嵌套定義,

   1:  有名的命名空間:
   2:   
   3:         namespace 命名空間名 {
   4:   
   5:                聲明序列可選
   6:   
   7:         }
   8:   
   9:  無名的命名空間:
  10:   
  11:         namespace {
  12:   
  13:                聲明序列可選
  14:   
  15:         }
  16:   

    在C++中,如果代碼的最前面沒有使用 using namespace std 的話,對於輸入輸出流,就必須指定所在的命名空間(std::cout <<),否則編譯器會找不到他們的具體實現。可以這么說,命名空間是對全局作用域的細分。

Linux中的namespace

    在Linux系統中,可以同時存在多用戶多進程,那么對他們的運行協調管理,通過進程調度和進度管理可以解決,但是,整體資源是有限的,怎么把有限的資源(進程號、通信資源、網絡資源等等)合理分配給各個用戶所在的進程?Linux中提出了namespace機制,這是一種輕量級的虛擬化形式。再次之前,Linux中很多資源是全局管理的,例如,系統中所有進程,都是通過PID來標識的,就像每個學生的學號一樣,在整個學校范圍內,肯定是唯一標識這個學生的。用戶的ID管理,各個用戶通過全局為UID來標識,每個學校的校長也只有有一個,它的UID為0,權利最大,可以對學校內全部老師和學生發起命令。每個學生可以看到其他學生的活動,但是無權把他們趕出學校,這是可以理解的。這種集中統一的管理方式,很適合大規模人群的管理。

    隨着大數據、虛擬化的興起,Linux為了提供更加精細的資源分配管理機制,給出了namespace機制解決方法。

image

命名空間建立系統的不同視圖, 對於每一個命名空間,從用戶看起來,應該像一台單獨的Linux計算機一樣,有自己的init進程(PID為0),其他進程的PID依次遞增,A和B空間都有PID為0的init進程,子容器的進程映射到父容器的進程上,父容器可以知道每一個子容器的運行狀態,而子容器與子容器之間是隔離的。

    Linux中有chroot的系統調用,該方法將進程限制到文件系統的某一部分,是一種簡單的命名空間機制。

    在task_struct結構體中,有struct nsproxy *nsproxy 這個成員變量,

   1:  /*
   2:   * A structure to contain pointers to all per-process
   3:   * namespaces - fs (mount), uts, network, sysvipc, etc.
   4:   *
   5:   * 'count' is the number of tasks holding a reference.
   6:   * The count for each namespace, then, will be the number
   7:   * of nsproxies pointing to it, not the number of tasks.
   8:   *
   9:   * The nsproxy is shared by tasks which share all namespaces.
  10:   * As soon as a single namespace is cloned or unshared, the
  11:   * nsproxy is copied.
  12:   */
  13:  struct nsproxy {
  14:      atomic_t count;
  15:      spinlock_t nslock;
  16:      struct uts_namespace *uts_ns;
  17:      struct ipc_namespace *ipc_ns;
  18:      struct mnt_namespace *mnt_ns;
  19:      struct pid_namespace *pid_ns;
  20:  };

uts_ns:UTS為Unix Timesharing System的簡稱,包含內存名稱、版本、底層體系結構等信息。

ipc_ns:保存所有與進程間通訊(IPC)有關的信息。

mnt_ns: 當前裝載的文件系統

pid_ns: 有關進程ID的信息

在高級版本上,還有net_ns的網絡信息,user_ns的資源配額的信息等。

下面以uts命名空間為例子,介紹如何創建用戶空間。

從上面的框架圖可以看出,所謂的子空間,就是父進程fork一個子進程出來,然后子進程與父進程不共享某些資源,那么,就可以說,這個子進程在它自己的那個命名空間內。

要達到這種效果,就必須對fork的行為進行精確控制,內核提供的如下參數來設置:

image

UTS命名空間沒有層次結構,所有信息都匯集到如下結構:

image ,kref是引用計數器,用於跟蹤內核中有多少地方使用uts_namespace的實例。它提供的屬性信息如下:

image ,從名字上,可以得知uts包含系統名稱、版本號、機器名稱等等。使用uname -a可以查看這些信息。

系統初始默認值保持在init/version.c 中的init_uts_ns全局變量中,在系統初始化task時,配置init_task。

用戶可以在fork時,傳入CLONE_NEWUTS標准,創建新的UTS命名空間。執行此操作,會生成先前uts_namespace的一份副本,當前進程內部的nsproxy指向此副本,然后就可以修改了。父子進程對nx_prosy的修改不會相互影響。

    由於最初的父命名空間需要掌握所有子命名空間的所有pid信息,所有,在各級層次的命名空間的fork中,pid的分配是需要統一協調控制,對於各級子命名空間中的task_struct來說,同一個pid在不同命名空間看到的是不一樣的。 

   同一個進程可以屬於多個namespace,多個進程可以使用同一個namespace,

參考鏈接:

C++中的namespace

PID namespace淺分析

PID namespcae淺分析 續

Linux內核的namespace機制分析

Technorati 標簽: namespace 內核


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM