我正在阅读装载 & 克隆手册页。 我想澄清CLONE_NEWNS如何影响subprocess的文件系统视图。
(文件层次结构)
让我们考虑这棵树是目录层次结构。 让我们说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_NEWNS
clone()
来创build一个subprocess,这是否意味着这个subprocess会得到树(5&6)中的挂载点的精确副本,并且仍然能够访问原始树的其余部分? 这是否也意味着孩子可以按照自己的意愿挂载5和6,而不影响父进程挂载名称空间中5或6挂载的内容。
如果是,是否也意味着孩子可以挂载/卸载不同于5或6的目录,并影响父进程可见的内容?
谢谢。
进程的“挂载名称空间”只是它所看到的一组挂载的文件系统。 一旦从具有一个全局挂载名称空间的传统情况转到具有每个进程挂载名称空间,则必须决定在使用clone()
创建子进程时要执行的操作。
传统上,挂载或卸载文件系统会改变文件系统,如所有进程所看到的那样:有一个全局挂载命名空间,所有进程都可以看到,如果做了任何更改(例如使用mount
命令),所有进程都会立即看到更改,而不管他们与mount
命令的关系。
通过每个进程的挂载命名空间,一个子进程现在可以有一个不同的挂载命名空间给它的父节点。 现在的问题出现了:
是否应该更改由该子级生成的挂载名称空间传播回父级?
显然,这个功能至少必须得到支持,实际上,必须是默认的。 否则,启动mount
命令本身将不会产生任何变化(因为父shell看到的文件系统不受影响)。
同样清楚的是,这个必要的传播也必须被抑制 ,否则我们永远不能创建一个子进程,它的挂载名称空间与父进程不同,我们又有一个全局挂载名字空间( init
所看到的文件系统)。
因此,我们必须决定何时使用clone()
方法创建子进程,子进程是否从父进程获取有关已装入文件系统的数据副本,可以在不影响父进程的情况下更改它,或者获取指向相同数据结构的指针作为它可以改变的父(作为从你的shell启动mount
时候需要传播的改变)。
如果将CLONE_NEWNS
标志传递给clone()
,则子代会获取其父文件系统数据的副本 ,在不影响父文件系统命名空间的情况下,该文件可以更改。 否则,它会得到一个指向父节点的装载数据结构的指针 ,父节点可以看到子节点所做的更改(因此mount
命令本身可以工作)。
现在,如果我使用CLONE_NEWNS的克隆来创建一个子进程,这是否意味着这个孩子将得到树(5&6)中的挂载点的精确副本,并且仍然能够访问原始树的其余部分?
是。 在调用clone()
之后,它看到与其父代完全相同的树。
这是否也意味着孩子可以按照自己的意愿挂载5和6,而不影响父进程挂载名称空间中5或6挂载的内容。
是。 由于您已经使用了CLONE_NEWNS
,孩子可以从5中卸载一个设备,并在其中挂载另一个设备,只有它(及其子)可以看到更改。 在这种情况下,没有其他进程可以看到孩子所做的更改。
如果是,是否也意味着孩子可以挂载/卸载不同于5或6的目录,并影响父进程可见的内容?
CLONE_NEWNS
。如果您使用了CLONE_NEWNS
,则在子项中所做的更改无法传播回父项。
如果你还没有使用CLONE_NEWNS
,那么这个孩子就会收到一个指向与其父母相同的挂载名称空间数据的指针,任何共享这些数据结构的进程(包括父进程)都会看到这个孩子所做的任何改变。 (当使用fork()
创建新的孩子的时候也是如此)
我没有足够的信誉点来添加评论,而是将此评论添加为答案。 这只是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; }
如果我错了,请纠正我