linux名稱空間(namespace)學習(二)
Linux的UTS名稱空間
在上一篇部落格裡面介紹了Linux名稱空間的使用,本部落格更新的部落格中更新下關於linuxUTS名稱空間的介紹以及使用方式;
UTS名稱空間,是關於linux主機命名或者核心版本命名的一套名稱空間,在此名稱空間中使用者感知的是一個單獨命名的的linux主機名稱,注意:僅僅是主機名稱,如果沒有結合其他名稱空間操作的話,使用者是感知不到一個單獨的主機名稱的;
一下是我學習linux的UTS名稱空間的一些思路:
1. UTS名稱空間在使用者層怎麼使用;
2. UTS名稱空間在核心中的應用;
3. UTS名稱空間怎麼和使用者的PID結合的;
我會根據以上三個問題一一介紹,可能第二點放在第三點之後講解,這樣組織結構更加清晰;
**
1.UTS名稱空間在使用者層怎麼使用
**
這一點在我的《linux名稱空間(namespace)學習(一)》中部落格中有具體的使用方式,在此不贅述;
**
2.UTS名稱空間怎麼和使用者的PID結合的;
**
UTS名稱空間和使用者空間和使用者PID結合的方式這句話可能有點繞,如果換句話說:UTS名稱空間在核心中的task_struct的表示方式,這句話就好多了。task_struct結構在核心中是表示一個唯一PID的一種方式,在核心中task_struct指向總體名稱空間的struct nsproxy *nsproxy;結構和所有名稱空間建立聯絡的。而struct nsproxy * nsproxy和核心中的所有型別的名稱空間建立聯絡;
其中和核心UTS名稱空間的資料聯絡結構如下:
如上圖所示的流程圖可以看出task_struct通過nsproxy指標一步可以找到utsnamspace結構。之後對與utsnamespace讀寫操操作;
資料結構如下:
struct task_struct{ ...... 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 net *net_ns; }; struct uts_namespace{ struct kref kref; struct new_utsname name; struct user_namespace *user_ns; };
**
3.UTS名稱空間在核心中的應用
**
關於UTS名稱空間在核心中的應用主要涉及如下幾點:
1. UTS名稱空間在clone帶CLONE_NEWUTS標誌過程中如何使用?
2. struct uts_namespace *copy_utsname(unsigned long flags,
struct task_struct *tsk)
{
struct uts_namespace *old_ns = tsk->nsproxy->uts_ns;
struct uts_namespace *new_ns;
BUG_ON(!old_ns);
get_uts_ns(old_ns);
if (!(flags & CLONE_NEWUTS))
return old_ns;
new_ns = clone_uts_ns(tsk, old_ns);
put_uts_ns(old_ns);
return new_ns;
}
先回答第一個問題,可能也是最複雜的問題: UTS名稱空間在clone帶CLONE_NEWUTS標誌過程中如何使用?
首先我們知道在《linux名稱空間(namespace)學習(一)》,如果CLONE帶CLONE_NEWUTS標誌,代表著建立一個新的UTS名稱空間。使用者子程序名稱空間和主程序命名空格鍵看到的主機名可能是一致的,也可能不一致;主要取決於使用者是否使用sethostname函式。但是這時候使用者子名稱空間和主程序名稱空間使用的名稱空間卻不是同一個實體地址了,為什麼呢?為了保證使用者子名稱空間和主程序名稱空間的獨立性,這樣使用者在設定主機名稱的時候不會影響到主程序名稱空間。主要由copy_utsname函式來起作用。原型如下:
struct uts_namespace *copy_utsname(unsigned long flags,
struct task_struct *tsk)
{
struct uts_namespace *old_ns = tsk->nsproxy->uts_ns;
struct uts_namespace *new_ns;
BUG_ON(!old_ns);
get_uts_ns(old_ns);
if (!(flags & CLONE_NEWUTS))
return old_ns;
new_ns = clone_uts_ns(tsk, old_ns);
put_uts_ns(old_ns);
return new_ns;
}
函式引數:
flags:clone函式呼叫的引數;
tsk:要克隆的主程序的task_struct;
函式返回值:
struct uts_name* 型別,返回的是UTS名稱空間的地址;
函式作用:
先判斷flags是否有CLONE_NEWUTS結構;
1.沒有,則返回老的uts_namespace;
2.有,先申請一塊記憶體再吧原來的uts_namespace拷貝給新的記憶體;
注意:在沒有CLONE_NEWUTS結構情況下會把uts_namespace->kref加一,否則不加一;
以上可以看出,如果clone時候flags標誌為沒有CLONE_NEWUTS標誌,只需要把舊的uts_namespace引用計數加一併返回就可以了,如果有CLONE_NEWUTS標誌則需要申請一段記憶體區域並且返回就OK了。這樣問題二的答案也就有了。