原:https://segmentfault.com/u/wuyangchun/articles?page=2
root@ubuntu:~# ls -l /proc/$$/ns
total 0
lrwxrwxrwx 1 root root 0 Nov 24 21:09 cgroup -> cgroup:[4026531835]
lrwxrwxrwx 1 root root 0 Nov 24 21:09 ipc -> ipc:[4026531839]
lrwxrwxrwx 1 root root 0 Nov 24 21:09 mnt -> mnt:[4026531840]
lrwxrwxrwx 1 root root 0 Nov 24 21:09 net -> net:[4026531957]
lrwxrwxrwx 1 root root 0 Nov 24 21:09 pid -> pid:[4026531836]
lrwxrwxrwx 1 root root 0 Nov 24 21:09 user -> user:[4026531837]
lrwxrwxrwx 1 root root 0 Nov 24 21:09 uts -> uts:[4026531838]
每个进程下都有一个ns目录
int clone(int (*child_func)(void *), void *child_stack
, int flags, void *arg);
int setns(int fd, int nstype);
int unshare(int flags);
root@nsnsns:~/linuxAdvanceProgame/namespace# ls -l /proc/$$/ns
total 0
lrwxrwxrwx 1 root root 0 Nov 24 22:00 cgroup -> cgroup:[4026531835]
lrwxrwxrwx 1 root root 0 Nov 24 22:00 ipc -> ipc:[4026531839]
lrwxrwxrwx 1 root root 0 Nov 24 22:00 mnt -> mnt:[4026531840]
lrwxrwxrwx 1 root root 0 Nov 24 22:00 net -> net:[4026531957]
lrwxrwxrwx 1 root root 0 Nov 24 22:00 pid -> pid:[4026531836]
lrwxrwxrwx 1 root root 0 Nov 24 22:00 user -> user:[4026531837]
lrwxrwxrwx 1 root root 0 Nov 24 22:00 uts -> uts:[4026532505]
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_for_children;
struct net *net_ns;
struct cgroup_namespace *cgroup_ns;
};
namespace的本质就是把原来所有进程全局共享的资源拆分成了很多个一组一组进程共享的资源
当一个namespace里面的所有进程都退出时,namespace也会被销毁,所以抛开进程谈namespace没有意义
UTS namespace就是进程的一个属性,属性值相同的一组进程就属于同一个namespace,跟这组进程之间有没有亲戚关系无关
clone和unshare都有创建并加入新的namespace的功能,他们的主要区别是:
unshare是使当前进程加入新创建的namespace
clone是创建一个新的子进程,然后让子进程加入新的namespace
UTS namespace没有嵌套关系,即不存在说一个namespace是另一个namespace的父namespace
#运行unshare创建新的ipc和uts namespace,并且在新的namespace中启动bash
#这里-i表示启动新的ipc namespace,-u表示启动新的utsnamespace
dev@ubuntu:~$ sudo unshare -iu /bin/bash
ipcmk -Q创建queue
ipcrm -q id 删除queue
ipcs -q 显示queue
unshare -iu /bin/bash
-m就是挂载信息的改变
dev@ubuntu:~/iso$ mkdir -p iso01/subdir01
dev@ubuntu:~/iso$ mkdir -p iso02/subdir02
dev@ubuntu:~/iso$ mkisofs -o ./001.iso ./iso01
dev@ubuntu:~/iso$ mkisofs -o ./002.iso ./iso02
dev@ubuntu:~/iso$ ls
001.iso 002.iso iso01 iso02
#准备目录用于mount
dev@ubuntu:~/iso$ sudo mkdir /mnt/iso1 /mnt/iso2
#查看当前所在的mount namespace
dev@ubuntu:~/iso$ readlink /proc/$$/ns/mnt
mnt:[4026531840]
#mount 001.iso 到 /mnt/iso1/
dev@ubuntu:~/iso$ sudo mount ./001.iso /mnt/iso1/
mount: /dev/loop1 is write-protected, mounting read-only
PID的namespace就是使PID的信息可以重复,父命名空间可以看到子孙命名空间的信息
除了在init进程里指定了handler的信号外,内核会帮init进程屏蔽掉其他任何信号,这样可以防止其他进程不小心kill掉init进程导致系统挂掉。不过有了PID namespace后,可以通过在父namespace中发送SIGKILL或者SIGSTOP信号来终止子namespace中的ID为1的进程。
在创建pid namespace的时候,必须要加上--fork
创建之后使用mount -t proc proc /proc
调用unshare或者setns函数后,当前进程的namespace不会发生变化,不会加入到新的namespace,而它的子进程会加入到新的namespace。也就是说进程属于哪个namespace是在进程创建的时候决定的,并且以后再也无法更改
sudo unshare --uts --pid --mount --fork --mount-proc /bin/bash (重新申请一个PS独立的namespace)