Linux Namespace : UTS

UTS namespace 用来隔离系统的 hostname 以及 NIS domain name。UTS 据称是 UNIX Time-sharing System 的缩写。

hostname 与 NIS domain name

hostname 是用来标识一台主机的,比如登录时的提示,在 Shell 的提示符上,都可以显示出来,这样的话,使用者可以知道自己用的是哪台机器。比如下图中的 nick@tigger:

Linux Namespace : UTS

nick 是用户名,而 tigger 就是主机的 hostname。我们可以通过 hostname 命令来查看当前主机的名称,比如上图中的输出:tigger。本质上,hostname 命令是通过执行系统调用 gethostname 来获得 hostname 的,我们在本文的结尾处会分析 gethostname 的相关实现。

NIS domain name
在一些大型的网络中,会有很多的 Linux 主机,如果能够有一部账号主控服务器来管理网络中所有主机的账号, 当其他的主机有用户登入的需求时,才到这部主控服务器上面请求相关的账号、密码等用户信息, 如此一来,如果想要增加、修改、删除用户数据,只要到这部主控服务器上面处理即可(听起来是不是有点类似 windows 平台上的域控制器的概念)。
Linux 平台上,一般通过 Network Information Services(NIS Server) 创建的域(domain)来实现相关的功能。而主机的 NIS domain name 就是加入 NIS domain 的主机显示的 NIS domain 的名称(类似 windows 平台上使用域控制器创建的域名)。

简单起见,本文以 hostname 为例进行 Linux UTS namespace 的介绍。文中的 demo 均在 ubuntu 16.04 中完成。

通过 clone 函数创建 UTS 隔离的子进程

我们在《Linux Namespace 简介》一文中介绍了 clone 函数用于在创建新进程的同时创建 namespace,下面的 demo 就是通过 clone 函数为新进程创建新的 UTS namespace(该 demo 的主要代码来自 clone 函数的 man page,为了进行演示,笔者进行了适当的调整和扩展):

#define _GNU_SOURCE #include <sys/wait.h> #include <sys/utsname.h> #include <sched.h> #include <string.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #define errExit(msg) do { perror(msg); exit(EXIT_FAILURE); } while (0) // 调用 clone 时执行的函数 static int childFunc(void *arg) { struct utsname uts; char *shellname; // 在子进程的 UTS namespace 中设置 hostname if (sethostname(arg, strlen(arg)) == -1) errExit("sethostname"); // 显示子进程的 hostname if (uname(&uts) == -1) errExit("uname"); printf("uts.nodename in child: %s\n", uts.nodename); printf("My PID is: %d\n", getpid()); printf("My parent PID is: %d\n", getppid()); // 获取系统的默认 shell shellname = getenv("SHELL"); if(!shellname){ shellname = (char *)"/bin/sh"; } // 在子进程中执行 shell execlp(shellname, shellname, (char *)NULL); return 0; } // 设置子进程的堆栈大小为 1M #define STACK_SIZE (1024 * 1024) int main(int argc, char *argv[]) { char *stack; char *stackTop; pid_t pid; if (argc < 2) { fprintf(stderr, "Usage: %s <child-hostname>\n", argv[0]); exit(EXIT_SUCCESS); } // 为子进程分配堆栈空间,大小为 1M stack = malloc(STACK_SIZE); if (stack == NULL) errExit("malloc"); stackTop = stack + STACK_SIZE; /* Assume stack grows downward */ // 通过 clone 函数创建子进程 // CLONE_NEWUTS 标识指明为新进程创建新的 UTS namespace pid = clone(childFunc, stackTop, CLONE_NEWUTS | SIGCHLD, argv[1]); if (pid == -1) errExit("clone"); // 等待子进程退出 if (waitpid(pid, NULL, 0) == -1) errExit("waitpid"); printf("child has terminated\n"); exit(EXIT_SUCCESS); }

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zwgszs.html