我想知道是否可以在 Linux 中加入两个进程名称空间。为了证明我的意思,以下是一个场景:
进程在其自己单独的命名空间中运行。我们将此过程称为 A。
现在进程 A 正在做它的事情,我启动了另一个进程 B,该进程被隔离在自己单独的命名空间内。
现在进程 A 和进程 B 都有自己独立的命名空间,但我希望将它们的进程命名空间“合并”为一个。即,我希望进程 B 能够看到 A 的命名空间并发送信号/与 A 的进程交互。
这样做的用例是,我最终希望将一个容器附加到另一个正在运行的容器,以便附加的容器可以与正在运行的容器交互。
我考虑过,setns()
但这行不通,因为进程 B 不知道进程 A 的名称空间句柄 ( /proc/PID/ns/pid
),因为它也是隔离的。我正在尝试思考从主机系统实现这一目标的最佳方法是什么。
这已经在docker中实现了这里但我无法理解其背后的逻辑。还讨论了一些实施方面的问题这里如果有帮助的话。
谢谢你的时间!
答案1
当我们谈论 Linux 命名空间时,我们实际上谈论的是许多不同的名称空间,所有这些都可以单独设置:
- 进程 ID
- 共享内存
- 联网
- 主机名等
- 用户 ID
- 文件系统
当一个进程使用正确的标志调用setns()
orclone()
时,就会产生一个新的名称空间,并带有“假”的世界视图。
现在,如果我们想再次将它们合并在一起,这可能会导致问题。
让我们采用“进程 ID”命名空间,因为它很简单。
当您创建新的 PID 命名空间时,第一个进程在该命名空间内获得 PID 1。如果你有两个新的命名空间,那么你就有两个认为它们的 PID 为 1 的进程。如果你想合并它们,那么就会发生冲突;只有其中一个可以保持 PID 1,你必须改变正在运行的进程的 PID 意外。这可能会产生意想不到的后果。
与 IPC 类似;两个独立的共享内存块在各自的命名空间内可以具有相同的地址;如果我们尝试合并它们,那么我们将看到内存损坏(即使您更改了一个段的地址,流程仍保留旧地址)。
因此合并两个现有的命名空间充满了危险。
补丁的作用docker
是防止容器启动时创建新的命名空间。这与合并两个现有容器不同;它发生在容器启动时。
答案2
据我所知,没有办法加入不同的进程命名空间。setns
在 PID 命名空间上只允许进程在不同的命名空间中生成子进程,并且该不同的命名空间必须是该进程的命名空间的后代,所以我认为这对您没有帮助。
但是,在您的场景中,两个命名空间看起来位于密切相关的树中。所以你可以从共同的祖先开始进行这种操作。
您引用的有关 Docker 的线程没有讨论合并命名空间:它们是关于不创建子命名空间(因此它仍然是一个大命名空间)。