25

我正在阅读mount & clone手册页。我想澄清 CLONE_NEWNS 如何影响子进程的文件系统视图。

(文件层次结构)

让我们将此树视为目录层次结构。让我们说 5 和 6 是父进程中的挂载点。我在另一个问题中阐明了挂载点。

所以我的理解是:5 和 6 是挂载点意味着该mount命令以前用于在 5 和 6 处“挂载”文件系统(目录层次结构)(这意味着 5 和 6 下也必须有目录树)。

mount手册页:

 A mount namespace is the set of filesystem mounts that are visible to a process. 

clone手册页:

Every process lives in a mount namespace.  The namespace of a process is the data 
(the set of mounts) describing the file hierarchy as seen by that process.  After 
a fork(2) or clone() where the CLONE_NEWNS flag is not set, the child lives in the 
same mount namespace as the parent.

还 :

After a clone() where the CLONE_NEWNS flag is set, the cloned child is started in a 
new mount namespace, initialized with a copy of the namespace of the parent.

现在,如果我使用clone()withCLONE_NEWNS创建一个子进程,这是否意味着子进程将获得树(5 和 6)中安装点的精确副本,并且仍然能够访问原始树的其余部分?这是否也意味着子进程可以随意挂载 5 和 6,而不会影响在其父进程的挂载命名空间中挂载在 5 或 6 的内容。

如果是,这是否也意味着子进程可以挂载/卸载不同于 5 或​​ 6 的目录并影响父进程可见的内容?

谢谢。

4

2 回答 2

29

进程的“挂载命名空间”只是它看到的一组挂载文件系统。一旦您从拥有一个全局挂载命名空间的传统情况转变为拥有每个进程的挂载命名空间,您必须决定在使用clone().

传统上,挂载或卸载文件系统会改变所有进程都可以看到的文件系统:有一个全局挂载命名空间,所有进程都可以看到,如果进行了任何更改(例如使用mount命令),所有进程都会立即看到该更改,而不管它们的与mount命令的关系。

使用每进程挂载命名空间,子进程现在可以拥有与其父进程不同的挂载命名空间。现在问题来了:

子级对挂载命名空间所做的更改是否应该传播回父级?

显然,至少必须支持此功能,并且实际上可能必须是默认功能。否则,启动mount命令本身不会影响任何更改(因为父 shell 看到的文件系统将不受影响)。

同样清楚的是,这种必要的传播也必须有可能被抑制,否则我们将永远无法创建其挂载命名空间与其父进程不同的子进程,并且我们再次拥有一个全局挂载命名空间(如图所示的文件系统init)。

因此,我们必须决定在创建子进程时clone(),子进程是从父进程获取有关已挂载文件系统的数据的自己的副本,它可以在不影响父进程的情况下更改它,还是获取指向与父进程相同的数据结构的指针,它可以更改(更改传播回来所必需的,就像mount从 shell 启动时一样)。

如果将CLONE_NEWNS标志传递给clone(),则子级将获得其父级已挂载文件系统数据的副本,它可以在不影响父级挂载命名空间的情况下对其进行更改。否则,它会获得一个指向父级挂载数据结构的指针,其中子级所做的更改将被父级看到(因此mount命令本身可以工作)。

现在,如果我使用带有 CLONE_NEWNS 的克隆来创建子进程,这是否意味着子进程将获得树(5 和 6)中安装点的精确副本,并且仍然能够访问原始树的其余部分?

是的。在调用 后,它会看到与其父级完全相同的树clone()

这是否也意味着子进程可以随意挂载 5 和 6,而不会影响在其父进程的挂载命名空间中挂载在 5 或 6 的内容。

是的。由于您使用过CLONE_NEWNS,孩子可以从 5 卸载一个设备并在那里安装另一个设备,并且只有它(及其孩子)可以看到更改。在这种情况下,没有其他进程可以看到孩子所做的更改。

如果是,这是否也意味着子进程可以挂载/卸载不同于 5 或​​ 6 的目录并影响父进程可见的内容?

不会。如果您使用过CLONE_NEWNS,则在子级中所做的更改无法传播回父级。

如果您没有使用CLONE_NEWNS,则子节点将收到指向与其父节点相同的挂载命名空间数据的指针,并且子节点所做的任何更改都将被共享这些数据结构的任何进程(包括父节点)看到。(使用 . 创建新孩子时也是如此fork()。)

于 2014-04-06T02:45:12.060 回答
6

我没有足够的声望点来添加评论,所以改为添加此评论作为答案。这只是对 Emmet 答案的补充。

AFAICU,如果创建的进程设置了 CLONE_NEWNS 标志,它只能挂载那些设置了 FS_USERNS_MOUNT 标志的文件系统。而且几乎所有基于磁盘的文件系统都没有设置这个标志(出于安全原因)。在 do_new_mount 中有这样的检查:

        if (user_ns != &init_user_ns) {
            if (!(type->fs_flags & FS_USERNS_MOUNT)) {
                    put_filesystem(type);
                    return -EPERM;
            }

如果我错了请纠正我

于 2014-10-28T08:16:33.990 回答