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 &current->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 详解的更多相关文章

  1. Linux ns 6. Network Namespace 详解

    文章目录 1. 简介 1.1 Docker Network 桥接模式配置 2. 代码解析 2.1 copy_net_ns() 2.2 pernet_list 2.2.1 loopback_net_op ...

  2. Linux ns 5. IPC Namespace 详解

    文章目录 1. 简介 2. 源码分析 2.1 copy_ipcs() 2.2 ipcget() 2.3 ipc_check_perms() 2.4 相关系统调用 参考文档: 1. 简介 进程间通讯的机 ...

  3. Linux ns 3. Mnt Namespace 详解

    1. 文件系统层次化 对 Linux 系统来说一切皆文件,Linux 使用树形的层次化结构来管理所有的文件对象. 完整的Linux文件系统,是由多种设备.多种文件系统组成的一个混合的树形结构.我们首先 ...

  4. Linux下DNS服务器搭建详解

    Linux下DNS服务器搭建详解 DNS  即Domain Name System(域名系统)的缩写,它是一种将ip地址转换成对应的主机名或将主机名转换成与之相对应ip地址的一种机制.其中通过域名解析 ...

  5. Linux上的free命令详解、swap机制

    Linux上的free命令详解   解释一下Linux上free命令的输出. 下面是free的运行结果,一共有4行.为了方便说明,我加上了列号.这样可以把free的输出看成一个二维数组FO(Free ...

  6. linux PHP 编译安装参数详解

    linux PHP 编译安装参数详解 ./configure --prefix=/usr/local/php --with-config-file-path=/usr/local/php/etc -- ...

  7. Linux Shell数组常用操作详解

    Linux Shell数组常用操作详解 1数组定义: declare -a 数组名 数组名=(元素1 元素2 元素3 ) declare -a array array=( ) 数组用小括号括起,数组元 ...

  8. Linux CAT与ECHO命令详解 <<EOF EOF

    Linux CAT与ECHO命令详解 cat命令是Linux下的一个文本输出命令,通常是用于观看某个文件的内容的: cat主要有三大功能: .一次显示整个文件. $ cat filename .从键盘 ...

  9. linux:SUID、SGID详解

    linux:SUID.SGID详解 文章转载至:http://tech.ccidnet.com/art/2583/20071030/1258885_1.html 如果你对SUID.SGID仍有迷惑可以 ...

随机推荐

  1. bzoj#4423-[AMPPZ2013]Bytehattan【并查集】

    正题 题目链接:https://darkbzoj.tk/problem/4423 题目大意 给出一个\(n*n\)的网格图,然后四联通的点之间连接.每次删掉一条边求这条边的两个点是否连通.强制在线. ...

  2. P4980-[模板]Pólya定理

    正题 题目链接:https://www.luogu.com.cn/problem/P4980 题目大意 \(n\)个物品图上\(m\)种颜色,求在可以旋转的情况下本质不同的涂色方案. 解题思路 既然是 ...

  3. oracle 不能用上下键调用sql语句

    在Linux的sqlplus中运行SQL语句之后,想用上下键把历史命令找出来,发现不支持. 安装rlwrap 重启sqlplus 3,使用rlwrap,rlwrap sqlplus / as sysd ...

  4. WebXml文件与SpringMVC的联系

    WebXml文件与SpringMVC的联系 无论采用何种框架来进行Java Web的开发,只要是Web项目必须在WEB-INF下有web.xml,这是java规范. 当然,我们最早接触到Java We ...

  5. 利用水文分析方法提取山脊线和山谷线(ArcPy实现)

    一.背景 作为地形特征线的山脊线.山谷线对地形.地貌具有一定的控制作用.它们与山顶点.谷底点以及鞍部点等一起构成了地形起伏变化的骨架结构.同时由于山脊线具有分水性,山谷线具有合水性特征,使得它们在地形 ...

  6. java笔记(一直更新)

    .equals()调用时,最好把equals前面放常量或者是确定有的,如果是前面是null,则会报空指针错误 也可以在调用前判断是否为null

  7. SpringBoot-邮件任务

    邮件发送,在我们的日常开发中,也非常的多,Springboot也帮我们做了支持 邮件发送需要引入spring-boot-start-mail SpringBoot 自动配置MailSenderAuto ...

  8. CentOS 文件管理

    目录 目录管理 目录结构 切换目录 查看目录 创建目录 复制目录 剪切目录 删除目录 文件管理 查看文件 创建文件 复制文件 剪切文件 删除文件 创建链接 目录管理 目录也是一种文件. 蓝色目录,绿色 ...

  9. Java RMI学习与解读(一)

    Java RMI学习与解读(一) 写在前面 本文记录在心情美丽的一个晚上. 嗯.就是心情很美丽. 那为什么晚上还要学习呢? emm... 卷... 卷起来. 全文基本都是根据su18师傅和其他师傅的文 ...

  10. MySQL:提高笔记-4

    MySQL:提高笔记-4 学完基础的语法后,进一步对 MySQL 进行学习,前几篇为: MySQL:提高笔记-1 MySQL:提高笔记-2 MySQL:提高笔记-3 MySQL:提高笔记-4,本文 说 ...