取消共享 --pid /bin/fork 无法分配内存



我正在试验Linux命名空间。 特别是 pid 命名空间。

我以为我会用 bash 测试一些东西,但遇到了这个问题:

unshare -p /bin/bash
bash: fork: Cannot allocate memory

从那里运行 ls 给出了一个核心转储。 退出是唯一可能的事情。

为什么要这样做?

该错误是由 PID 1 进程在新命名空间中退出引起的。

在 bash 开始运行后,bash 将分叉几个新的子进程来做一些事情。如果你在没有 -f 的情况下运行取消共享,bash 将具有与当前"取消共享"进程相同的 pid。当前的"取消共享"进程调用取消共享系统调用,创建一个新的 pid 命名空间,但当前的"取消共享"进程不在新的 pid 命名空间中。这是 linux 内核的预期行为:进程 A 创建一个新的命名空间,进程 A 本身不会被放入新的命名空间中,只有进程 A 的子进程将被放入新的命名空间中。因此,当您运行时:

unshare -p

/bin/bash取消共享进程将执行/bin/bash,/bin/bash 分叉几个子进程,bash 的第一个子进程将成为新命名空间的 PID 1,子进程在完成作业后退出。因此,新命名空间的 PID 1 退出。

PID 1 进程有一个特殊功能:它应该成为所有孤立进程的父进程。如果根命名空间中的 PID 1 进程退出,内核将死机。如果子命名空间中的 PID 1 进程退出,Linux 内核将调用 disable_pid_allocation 函数,该函数将清理该命名空间中的 PIDNS_HASH_ADDING 标志。当 linux 内核创建新进程时,内核将调用alloc_pid函数在命名空间中分配 PID,如果未设置 PIDNS_HASH_ADDING 标志,alloc_pid函数将返回 -ENOMEM 错误。这就是您收到"无法分配内存"错误的原因。

您可以使用"-f"选项解决此问题:

取消共享 -fp/bin/bash

如果使用"-f"选项运行取消共享,则取消共享将在创建新的 pid 命名空间后分叉一个新进程。并在新进程中运行/bin/bash。新进程将是新 pid 命名空间的 pid 1。然后 bash 还会分叉几个子进程来完成一些工作。由于 bash 本身是新 pid 命名空间的 pid 1,因此它的子进程可以毫无问题地退出。

这并没有解释为什么会发生这种情况,但展示了如何在新的 pid 命名空间中正确启动 shell:

使用-f标志从unshare中分叉外壳,以便新 shell 在新创建的命名空间中获得 PID 1:

unshare -fp /bin/bash

您可能还希望传递--mount-proc选项,以便您的ps列表反映新创建的 PID 命名空间,而不是父 PID 命名空间:

unshare -fp --mount-proc /bin/bash

现在运行ps

# ps
PID TTY          TIME CMD
1 pts/1    00:00:00 bash
11 pts/1    00:00:00 ps

相关内容

  • 没有找到相关文章

最新更新