Linux ns 3. Mnt Namespace 详解
1. 文件系统层次化
对 Linux 系统来说一切皆文件,Linux 使用树形的层次化结构来管理所有的文件对象。
完整的Linux文件系统,是由多种设备、多种文件系统组成的一个混合的树形结构。我们首先从一个单独的块设备来分析其树形结构的构造。
1.1 块设备的层次化(superblock/inode/dentry)
对一个块设备来说要想构造文件系统树形结构,最重要的两个全局因素是:块设备(block_device)和文件系统(file_system_type)。内核使用了一个数据结构 struct super_block
把这两者结合起来,用来标识一个块设备。
确定了 super_block 以后,就可以使用文件系统提供的方法来解析块设备的内容,形成一个块设备内部的树形结构,也就是我们熟悉的文件夹、文件的层次结构。
系统使用 struct inode
结构来标识块设备内部的一个文件夹或者文件,struct inode
结构中最重要的成员是 ->i_ino
这个记录了 inode 在块设备中的偏移。
系统为了辅助 struct inode
的使用还设计了一个 struct dentry
结构,通常情况下一个 struct dentry
对应一个 struct inode
,也有少数情况下多个 struct dentry
对应一个 struct inode
(如硬链接)。struct dentry
中 cache 了更多的文件信息,类如文件名、层次结构,成员 ->d_parent
指向同一块设备内的父节点 struct dentry
,成员 ->d_subdirs
链接了所有的子节点 struct dentry
。
1.2 多设备的层次化(mount/vfsmount)
上一节描述了单个块设备构建树形文件系统的方式,如果是多个设备怎么样组成一颗更复杂的树呢?
Linux使用父子树的形式来构造,父设备树中的一个文件夹 struct dentry
可以充当子设备树的挂载点 mountpoint
。
- mount/vfsmount
为了组成复杂的父子树,系统定义了一个 struct mount
结构来负责对一个设备内子树的引用。
- mount tree
可以看到通过一个 struct mount
结构负责引用一颗子设备树,把这颗子设备树挂载到父设备树的其中一个 dentry
节点上。
如果 dentry
成为了挂载点 mountpoint
,会给其标识成 DCACHE_MOUNTED
。我们在查找路径的时候同样会判断 dentry
的 DCACHE_MOUNTED
标志,一旦置位就变成了 mountpoint
,挂载点文件夹下原有的内容就不能访问了,转而访问子设备树根节点下的内容。
struct mount
结构之间也构成了树形结构。
我们通常使用 mount -t fstpye devname pathname
命令来进行挂载子设备的操作。Linux 拥有非常灵活的挂载规则:
规则1、一个设备可以被挂载多次:
可以看到同一个子设备树,同时被两个 struct mount
结构所引用,被挂载到父设备树的两处不同的 dentry
处。
特别说明:虽然子设备树被挂载两次并且通过两处路径都能访问,但子设备的
dentry
和inode
只保持一份。
规则2、一个挂载点可以挂载多个设备:
还可以对父设备树的同一个文件夹 dentry
进行多次挂载,最后路径查找时生效的是最后一次挂载的子设备树。
- path
因为linux提供的灵活的挂载规则,所以我们如果要标识一个路径 struct path
的话需要两个元素:vfsmount
和 dentry
。
可以看到两个路径 struct path
最后引用到了同一 inode
,但是路径 path
是不一样的,因为 path
指向的 vfsmount
是不一样的。
- chroot
Linux 还支持每个进程拥有不同的根目录,使用 chroot()
系统调用可以把当前进程的根目录设置为整棵文件系统树中的任何 path
。
1.3 多名空间的层次化(mnt_namespace)
之前的系统中只有一棵mount
树,为了支持mnt_namespace
,系统把mount
树叶扩展成了多棵。每个mnt_namespace
拥有一棵独立的mount
树:
2. 关键代码
2.1 mount()
mount() 系统调用是理解文件系统层次化的核心,它主要包含3个关键步骤:
1、解析 mount() 系统调用中的参数挂载点路径 pathname
,返回对应的 struct path
结构:
SYSCALL_DEFINE5(mount) → do_mount() → user_path() → user_path_at_empty() → filename_lookup() → path_lookupat() → link_path_walk() → walk_component() → follow_managed()
2、解析 mount() 系统调用中的参数文件系统类型 -t type
和设备路径 devname
,建立起子设备的树形结构(如果之前已经创建过引用即可),建立起新的 struct mount
结构对其引用:
SYSCALL_DEFINE5(mount) → do_mount() → do_new_mount() → vfs_kern_mount() → mount_fs() → type->mount()
3、将新建立的 struct mount
结构挂载到查找到的 struct path
结构上:
SYSCALL_DEFINE5(mount) → do_mount() → do_new_mount() → do_add_mount() → graft_tree() → attach_recursive_mnt() → commit_tree()
2.2 chroot()
更改当前进程的根目录:
SYSCALL_DEFINE1(chroot, const char __user *, filename)
{
struct path path;
int error;
unsigned int lookup_flags = LOOKUP_FOLLOW | LOOKUP_DIRECTORY;
retry:
/* (1) 解析指定的路径,返回对应的`struct path`结构 */
error = user_path_at(AT_FDCWD, filename, lookup_flags, &path);
if (error)
goto out;
error = inode_permission(path.dentry->d_inode, MAY_EXEC | MAY_CHDIR);
if (error)
goto dput_and_out;
error = -EPERM;
if (!ns_capable(current_user_ns(), CAP_SYS_CHROOT))
goto dput_and_out;
error = security_path_chroot(&path);
if (error)
goto dput_and_out;
/* (2) 把`struct path`结构设置为当前进程的根目录 */
set_fs_root(current->fs, &path);
error = 0;
dput_and_out:
path_put(&path);
if (retry_estale(error, lookup_flags)) {
lookup_flags |= LOOKUP_REVAL;
goto retry;
}
out:
return error;
}
↓
void set_fs_root(struct fs_struct *fs, const struct path *path)
{
struct path old_root;
path_get(path);
spin_lock(&fs->lock);
write_seqcount_begin(&fs->seq);
old_root = fs->root;
/* (2.1) 替换新的根目录 */
fs->root = *path;
write_seqcount_end(&fs->seq);
spin_unlock(&fs->lock);
if (old_root.dentry)
path_put(&old_root);
}
2.3 copy_mnt_ns()
在进程创建或者 unshare()/setns() 系统调用时,如果设置了 CLONE_NEWNS
标志会调用 copy_mnt_ns() 创建一个新的 mnt namespace。其中的核心是创建一颗新的 struct mount
树,首先把旧的 struct mount
树复制过来:
SYSCALL_DEFINE1(unshare) → unshare_nsproxy_namespaces() → create_new_namespaces() → copy_mnt_ns() → copy_tree() → clone_mnt()
随后如果有新的 mount()
动作,两棵树的内容就会不同。
参考文档:
1.Linux Namespace
2.Linux文件系统
3.在CentOS7上使用LXC管理容器
4.docker基础:从chroot理解namespace的隔离
5.Docker基础: Linux内核命名空间之(1)mnt namespace
6.Docker基础:文件系统之AUFS
7.docker image是什么,存储在什么位置
8.Docker镜像存储-overlayfs
9.linux文件系统之mount流程分析
10.dentry和inode的关系
Linux ns 3. Mnt Namespace 详解的更多相关文章
- 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 ge ...
- 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 ...
- Linux ns 5. IPC Namespace 详解
文章目录 1. 简介 2. 源码分析 2.1 copy_ipcs() 2.2 ipcget() 2.3 ipc_check_perms() 2.4 相关系统调用 参考文档: 1. 简介 进程间通讯的机 ...
- Linux下的文件目录结构详解
Linux下的文件目录结构详解 / Linux文件系统的上层根目录 /bin 存放用户可执行的程序 /boot 操作系统启动时所需要的文件 /dev 接口设备文件目录,例如:had表示硬盘 /etc ...
- Linux文件系统的目录结构详解
Linux文件系统的目录结构详解 一.前 言 文章对Linux下所有目录一一说明,对比较重要的目录加以重点解说,以帮助初学者熟练掌握Linux的目录结构. 二.目 录 1.什么是文件系统 2.文件 ...
- Linux文件权限与属性详解 之 ACL
Linux文件权限与属性详解 之 一般权限 Linux文件权限与属性详解 之 ACL Linux文件权限与属性详解 之 SUID.SGID & SBIT Linux文件权限与属性详解 之 ch ...
- Linux下DNS服务器搭建详解
Linux下DNS服务器搭建详解 DNS 即Domain Name System(域名系统)的缩写,它是一种将ip地址转换成对应的主机名或将主机名转换成与之相对应ip地址的一种机制.其中通过域名解析 ...
- Linux自带神器logrotate详解
Linux自带神器logrotate详解 散尽浮华 运维 3天前 作者:散尽浮华 链接:https://www.cnblogs.com/kevingrace/p/6307298.html 对于 L ...
- Linux上的free命令详解、swap机制
Linux上的free命令详解 解释一下Linux上free命令的输出. 下面是free的运行结果,一共有4行.为了方便说明,我加上了列号.这样可以把free的输出看成一个二维数组FO(Free ...
随机推荐
- selenium+python处理Alert弹窗
from selenium import webdriver import win32api import win32con from time import sleep driver = webdr ...
- re.findall用法
其中,re.findall() 函数可以遍历匹配,可以获取字符串中所有匹配的字符串,返回一个列表. 在python源代码中,展示如下: 搜索string,返回一个顺序访问每一个匹配结果(Match对象 ...
- 羽夏逆向破解日记簿——RunAsDate的实现原理分析
前言 RunAsDate是一个小工具,允许您在指定的日期和时间运行程序,不过有人用它来破解有时间限制了.此实用程序不会更改计算机的当前系统日期和时间,但只会将指定的日期/时间注入所需的应用程序.该 ...
- HTML对溢出的控制:overflow
用于对超出模块的内容进行控制 overflow的三种参数 1.visible(默认):溢出部分可见 2.hidden:溢出部分隐藏 3.auto:适当加入滚动条 overflow使用方法 1.常用 o ...
- Linux Bash命令杂记(cut sort uniq wc tee)
Linux Bash命令杂记(cut sort uniq wc tee) 数据流重定向 标准输入(stdin):代码为0,使用<或<<: 标准输出(stdout):代码为1,使用&g ...
- C 可变参数列表 stdarg.h
内容来自<c和指针>,整理后方便个人理解 stdarg.h 菜鸟教程 - <stdarg.h> 类型 va_list 宏 va_start va_arg va_end #inc ...
- HCNP Routing&Switching之BGP邻居建立条件、优化和认证
前文我们了解了BGP相关概念.AS相关概念以及BGP邻居类型.基础配置等,相关回顾请参考https://www.cnblogs.com/qiuhom-1874/p/15370838.html:今天我们 ...
- Java(31)泛型和可变参数
作者:季沐测试笔记 原文地址:https://www.cnblogs.com/testero/p/15228443.html 博客主页:https://www.cnblogs.com/testero ...
- 内网渗透DC-3靶场通关
个人博客:点我 DC系列共9个靶场,本次来试玩一下DC-3,只有1个flag,下载地址. 下载下来后是 .ova 格式,建议使用vitualbox进行搭建,vmware可能存在兼容性问题.靶场推荐使用 ...
- mall笔记
介绍 SpringBoot.SpringCloud.SpringCloudAlibaba.Nacos.Sentinel.Seata整合demo. 软件架构 JDK 1.8 Spring Boot 2. ...