简短的回答:它看起来像的mount propagation类型设置不正确。
说明
起初,你的根挂载点的传播类型,应该是MS_SHARED
,作为启动设置由systemd。 这可以通过查看/proc/$PID/mountinfo
的可选字段来观察。 例如,像这样可以预料:
$ cat /proc/self/mountinfo
. . .
25 0 8:6// rw,relatime shared:1 - ext4 /dev/sda6 rw,errors=remount-ro,data=ordered
^^^^^^
. . .
通知的加下划线(由我)shared:1
场以上,表明/
当前传播类型挂载点是MS_SHARED
,并且对等体组 ID是1
(在我们的例子中,我们根本不会在乎同伴组ID)。
当使用clone(2)
上的CLONE_NEWNS
标志时,会创建一个新的挂载名称空间,该空间将初始化为调用者的挂载名称空间的副本。 新名称空间的新复制挂载点将与其在调用程序的挂载名称空间中各自的原始挂载点加入同一对等组。
其父传播类型为MS_SHARED
的新安装点的传播类型也为MS_SHARED
。因此,当您的“包含”进程mount()
是循环设备上的文件系统时,安装程序默认为MS_SHARED
。之后,它下面的所有挂载也会传播到“主”进程的命名空间,这就是“主”进程可以看到它们的原因。
对于你的要求得到满足(为“主”过程中没有看见“载”进程的挂载点),你所寻求的挂载传播类型是MS_SLAVE
或MS_PRIVATE
,这取决于你是否希望你的“载”进程的根挂载点分别接收来自其他对等体的传播事件。 显然,MS_PRIVATE
提供比MS_SLAVE
更大的隔离度。
因此,在你的情况下,它应该是足以改变“载”进程的根的传播类型,挂载点MS_PRIVATE
或MS_SLAVE
之前挂载文件系统的其余部分,所以坐骑将不会传播到“主”进程的名字空间。
代码
起初,一会尝试来正确设置传播类型当“包含”的过程产生其根挂载点。
不过,我注意到在man 8 mount
以下(引用):
注意的是,Linux内核不允许更改多个 传播标志使用单个安装(2)系统调用和标志 不能与其他安装选项混合使用。
由于util-linux 2.23的安装命令允许使用几个 传播标志一起,并与其他安装 操作一起使用。此功能是实验性的。当前面的安装 操作成功时,传播标志是 由附加安装(2)系统调用应用。
看你的代码中,“载”的过程,之后mount()
■循环设备上的文件系统,它会发出chroot()
它。在这一点上,你可以通过注射这种mount(2)
呼叫建立其传播类型:
if (chroot(".") < 0) {
// handle error
}
if (mount("/", "/", c->fstype, MS_PRIVATE, "") < 0) {
// handle error
}
if (mkdir(...)) {
// handle error
}
现在传播类型设置为MS_PRIVATE
,所有后续坐骑“载”过程/
下确实将不会传播,因此在“主”进程的名称空间中不可见,正如您在/proc/mounts
或/proc/$PID/mountinfo
中观察到的那样。
资源
这是一个很好的答案,谢谢! – dmitrievanthony