namespace[1]提供一种隔离机制,让不同的namespace下的进程看到的全局资源不同,每一个namespace有一个自己独立的全局资源实例。
namespace的一个用途是实现容器
image.png

Linux系统下的namespace类型

名称 API中使用的标识 手册 隔离的资源
Cgroup CLONE_NEWCGROUP cgroup_namespaces(7) Cgroup root directory
IPC CLONE_NEWIPC ipc_namespaces(7) System V IPC, POSIX message queues
Network CLONE_NEWNET network_namespaces(7) Network devices,stacks,ports,etc.
Mount CLONE_NEWNS mount_namespaces(7) Mount points
PID CLONE_NEWPID pid_namespaces(7) Process IDs
Time CLONE_NEWTIME time_namespaces(7) Boot and monotonic clocks
User CLONE_NEWUSER user_namespaces(7) User and group IDs
UTS CLONE_NEWUTS uts_namespaces(7) Hostname and NIS domain name

namespace相关系统调用

clone 创建新进程,flags参数可以用来创建新的namespace
setns 让进程加入存在的namespace
unshare 将调用进程移动到新的namespace中
ioctl_ns 查看namespace的信息

进程namespace目录

/proc/[pid]/ns/cgroup 进程cgroup命名空间句柄
/proc/[pid]/ns/ipc 进程IPC命名空间句柄
/proc/[pid]/ns/mnt 进程mount命名空间句柄
/proc/[pid]/ns/net 进程网络命名空间句柄
/proc/[pid]/ns/pid 进程PID命名空间句柄
/proc/[pid]/ns/pid_for_children 该进程的子进程的PID命名空间句柄
/proc/[pid]/ns/time 进程time命名空间句柄
/proc/[pid]/ns/user 进程user命名空间句柄
/proc/[pid]/ns/uts 进程UTS命名空间句柄

namespace limit

/proc/sys/user目录
max_cgroup_namespaces
max_inotify_instances
max_inotify_watches
max_ipc_namespaces
max_mnt_namespaces
max_net_namespaces
max_pid_namespaces
max_user_namespaces
max_uts_namespaces

namespace生命周期

namespace中的最后一个进程结束或离开namespace,该namespace生命周期结束

  1. #define _GNU_SOURCE
  2. #include <sys/wait.h>
  3. #include <sys/utsname.h>
  4. #include <sched.h>
  5. #include <string.h>
  6. #include <stdio.h>
  7. #include <stdlib.h>
  8. #include <unistd.h>
  9. #include <sys/mman.h>
  10. int static new_world() {
  11. printf("new world\n");
  12. execlp("/bin/bash", "bash", NULL);
  13. return 0;
  14. }
  15. /**
  16. * clone出来新进程的栈大小
  17. */
  18. #define STACK_SIZE (1024*1024)
  19. int main() {
  20. // linux clone函数
  21. // http://www.man7.org/linux/man-pages/man2/clone.2.html
  22. char *stack;
  23. char *stackTop;
  24. pid_t pid;
  25. struct utsname uts;
  26. //给新进程分配栈空间
  27. stack = mmap(NULL, STACK_SIZE, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1, 0);
  28. if (stack == MAP_FAILED) {
  29. printf("mmap failed!\n");
  30. exit(-1);
  31. }
  32. stackTop = stack + STACK_SIZE;
  33. //clone一个新进程出来
  34. //Notice: Only a privileged process (CAP_SYS_ADMIN) can employ CLONE_NEWCGROUP.
  35. //也就是说必须要用root用户才能执行该程序
  36. pid = clone(new_world, stackTop,
  37. CLONE_NEWCGROUP | CLONE_NEWIPC | CLONE_NEWNET | CLONE_NEWNS | CLONE_NEWUTS | SIGCHLD, NULL);
  38. if (pid == -1) {
  39. printf("clone failed!\n");
  40. exit(-1);
  41. }
  42. if (waitpid(pid, NULL, 0) == -1) {
  43. printf("waitpid failed\n");
  44. exit(-1);
  45. }
  46. printf("child has terminated\n");
  47. return EXIT_SUCCESS;
  48. }


NOTICE:
运行该程序后执行 ls /proc/$$/ns可以查看当前bash进程的namespace

相关命令

lsns 命令可以查看系统下所有的namespace
/proc/[pid]/ns 伪文件系统下记录了进程的所有namespace

[1] https://www.man7.org/linux/man-pages/man7/namespaces.7.html