Linux ns 4. UTS Namespace 详解
2021/5/16 7:28:11
本文主要是介绍Linux ns 4. UTS Namespace 详解,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
文章目录
- 1. 使用简介
- 1.1 hostname
- 1.2 domainname
- 1.3 uname
- 2. 代码分析
- 2.1 copy_utsname()
- 2.2 sethostname()
- 2.3 gethostname()
- 2.4 setdomainname()
- 2.5 uname()
- 参考文档:
1. 使用简介
UTS(UNIX Time Sharing) namespace 是最简单的一种 namespace。UTS 中主要包含了主机名(hostname)、域名(domainname)和一些版本信息:
struct uts_namespace { struct kref kref; struct new_utsname name; // UTS 主要存储的信息 struct user_namespace *user_ns; struct ucounts *ucounts; struct ns_common ns; } __randomize_layout; ↓ struct new_utsname { char sysname[__NEW_UTS_LEN + 1]; char nodename[__NEW_UTS_LEN + 1]; // host name char release[__NEW_UTS_LEN + 1]; char version[__NEW_UTS_LEN + 1]; char machine[__NEW_UTS_LEN + 1]; char domainname[__NEW_UTS_LEN + 1]; // domain name };
其中主机名(hostname)、域名(domainname)是可以被修改的,其他只能被读取。UTS 的主要作用就是给用户态、内核态提供这些信息。
1.1 hostname
针对主机名(hostname),系统提供了 hostname
命令来进行读取和设置。下面举例说明其使用方法:
1、查看普通进程的 hostname :
pwl@ubuntu:~$ hostname ubuntu // 当前 hostname 为 ubuntu
2、创建一个新的 UTS namespace,并设置新的 hostname :
pwl@ubuntu:~$ sudo unshare --uts /bin/bash [sudo] password for pwl: root@ubuntu:~# hostname ubuntu root@ubuntu:~# hostname test root@ubuntu:~# hostname test // 在新的 UTS namespace 中更改 hostname 为 test pwl@ubuntu:~$ hostname ubuntu // 在旧的 UTS namespace 中的 hostname 仍然为 ubuntu
1.2 domainname
针对域名(domainname),系统提供了 domainname
命令来进行读取和设置。下面举例说明其使用方法:
1、查看普通进程的 hostname :
pwl@ubuntu:~$ domainname (none) // 当前 hostname 为空
2、创建一个新的 UTS namespace,并设置新的 hostname :
pwl@ubuntu:~$ domainname (none) pwl@ubuntu:~$ sudo unshare --uts /bin/bash root@ubuntu:~# domainname (none) root@ubuntu:~# domainname test root@ubuntu:~# domainname test // 在新的 UTS namespace 中更改 hostname 为 test root@ubuntu:~# pwl@ubuntu:~$ domainname (none) // 在旧的 UTS namespace 中的 hostname 仍然为空
1.3 uname
针对 UTS 提供的其他信息,系统提供了 uname
命令来进行读取,且不支持配置。
pwl@ubuntu:~$ uname -a Linux ubuntu 4.15.0-123-generic #126-Ubuntu SMP Wed Oct 21 09:40:11 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux pwl@ubuntu:~$ uname --help Usage: uname [OPTION]... Print certain system information. With no OPTION, same as -s. -a, --all print all information, in the following order, except omit -p and -i if unknown: -s, --kernel-name print the kernel name -n, --nodename print the network node hostname -r, --kernel-release print the kernel release -v, --kernel-version print the kernel version -m, --machine print the machine hardware name -p, --processor print the processor type (non-portable) -i, --hardware-platform print the hardware platform (non-portable) -o, --operating-system print the operating system --help display this help and exit --version output version information and exit
2. 代码分析
我们简单分析一下 UTS namespace 的创建代码,以及几个相关系统调用的代码。
2.1 copy_utsname()
在进程创建或者 unshare()/setns() 系统调用时,如果设置了 CLONE_NEWUTS
标志会调用 copy_utsname() 创建一个新的 UTS namespace。其中的核心是创建一个新的 struct uts_namespace
结构,首先把旧的 struct uts_namespace
树复制过来:
struct uts_namespace *copy_utsname(unsigned long flags, struct user_namespace *user_ns, struct uts_namespace *old_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(user_ns, old_ns); put_uts_ns(old_ns); return new_ns; } ↓ static struct uts_namespace *clone_uts_ns(struct user_namespace *user_ns, struct uts_namespace *old_ns) { struct uts_namespace *ns; struct ucounts *ucounts; int err; err = -ENOSPC; ucounts = inc_uts_namespaces(user_ns); if (!ucounts) goto fail; err = -ENOMEM; /* (1) 创建一个新的 uts namespace 结构 */ ns = create_uts_ns(); if (!ns) goto fail_dec; /* (2) 分配一个新的 namespace 编号 */ err = ns_alloc_inum(&ns->ns); if (err) goto fail_free; ns->ucounts = ucounts; ns->ns.ops = &utsns_operations; down_read(&uts_sem); /* (3) 拷贝旧的 uts namespace 的内容 */ memcpy(&ns->name, &old_ns->name, sizeof(ns->name)); ns->user_ns = get_user_ns(user_ns); up_read(&uts_sem); return ns; fail_free: kfree(ns); fail_dec: dec_uts_namespaces(ucounts); fail: return ERR_PTR(err); }
后面使用 sethostname()/setdomainname() 系统调用来独立的设置各个 uts namespace 下的 hostname/domainname。
2.2 sethostname()
SYSCALL_DEFINE2(sethostname, char __user *, name, int, len) { int errno; char tmp[__NEW_UTS_LEN]; if (!ns_capable(current->nsproxy->uts_ns->user_ns, CAP_SYS_ADMIN)) return -EPERM; if (len < 0 || len > __NEW_UTS_LEN) return -EINVAL; errno = -EFAULT; if (!copy_from_user(tmp, name, len)) { struct new_utsname *u; down_write(&uts_sem); u = utsname(); /* (1) 设置当前 uts namespace 中的 uts_ns->name->nodename */ memcpy(u->nodename, tmp, len); memset(u->nodename + len, 0, sizeof(u->nodename) - len); errno = 0; uts_proc_notify(UTS_PROC_HOSTNAME); up_write(&uts_sem); } return errno; } ↓ static inline struct new_utsname *utsname(void) { return ¤t->nsproxy->uts_ns->name; }
2.3 gethostname()
SYSCALL_DEFINE2(gethostname, char __user *, name, int, len) { int i; struct new_utsname *u; char tmp[__NEW_UTS_LEN + 1]; if (len < 0) return -EINVAL; down_read(&uts_sem); u = utsname(); i = 1 + strlen(u->nodename); if (i > len) i = len; /* (1) 获取当前 uts namespace 中的 uts_ns->name->nodename */ memcpy(tmp, u->nodename, i); up_read(&uts_sem); if (copy_to_user(name, tmp, i)) return -EFAULT; return 0; }
2.4 setdomainname()
SYSCALL_DEFINE2(setdomainname, char __user *, name, int, len) { int errno; char tmp[__NEW_UTS_LEN]; if (!ns_capable(current->nsproxy->uts_ns->user_ns, CAP_SYS_ADMIN)) return -EPERM; if (len < 0 || len > __NEW_UTS_LEN) return -EINVAL; errno = -EFAULT; if (!copy_from_user(tmp, name, len)) { struct new_utsname *u; down_write(&uts_sem); u = utsname(); /* (1) 设置当前 uts namespace 中的 uts_ns->name->domainname */ memcpy(u->domainname, tmp, len); memset(u->domainname + len, 0, sizeof(u->domainname) - len); errno = 0; uts_proc_notify(UTS_PROC_DOMAINNAME); up_write(&uts_sem); } return errno; }
2.5 uname()
SYSCALL_DEFINE1(newuname, struct new_utsname __user *, name) { struct new_utsname tmp; down_read(&uts_sem); /* (1) 获取当前 uts namespace 中的所有信息 */ memcpy(&tmp, utsname(), sizeof(tmp)); up_read(&uts_sem); if (copy_to_user(name, &tmp, sizeof(tmp))) return -EFAULT; if (override_release(name->release, sizeof(name->release))) return -EFAULT; if (override_architecture(name)) return -EFAULT; return 0; }
参考文档:
1.UTS namespace详解
2.Linux内核命名空间之(4)uts namespace
这篇关于Linux ns 4. UTS Namespace 详解的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-23linux 系统宝塔查看网站访问的命令是什么?-icode9专业技术文章分享
- 2024-11-12如何创建可引导的 ESXi USB 安装介质 (macOS, Linux, Windows)
- 2024-11-08linux的 vi编辑器中搜索关键字有哪些常用的命令和技巧?-icode9专业技术文章分享
- 2024-11-08在 Linux 的 vi 或 vim 编辑器中什么命令可以直接跳到文件的结尾?-icode9专业技术文章分享
- 2024-10-22原生鸿蒙操作系统HarmonyOS NEXT(HarmonyOS 5)正式发布
- 2024-10-18操作系统入门教程:新手必看的基本操作指南
- 2024-10-18初学者必看:操作系统入门全攻略
- 2024-10-17操作系统入门教程:轻松掌握操作系统基础知识
- 2024-09-11Linux部署Scrapy学习:入门级指南
- 2024-09-11Linux部署Scrapy:入门级指南