unshare --pid / bin / bash - fork无法分配内存

时间:2017-06-21 04:03:46

标签: linux bash linux-namespaces

我正在尝试使用linux命名空间。特别是pid命名空间。

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

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

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

为什么这样做?

2 个答案:

答案 0 :(得分:14)

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

在bash开始运行之后,bash将分叉几个新的子进程来做某些事情。如果你在没有-f的情况下运行unshare,bash将拥有与当前" unshare"相同的pid。处理。当前"取消共享"进程调用unshare systemcall,创建一个新的pid命名空间,但是当前" unshare"进程不在新的pid命名空间中。这是linux内核的理想行为:进程A创建一个新的命名空间,进程A本身不会被放入新的命名空间,只有进程A的子进程将被放入新的命名空间。所以当你跑:

unshare -p /bin/bash

unhare进程将exec / 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'来解决此问题。选项:

unshare -fp /bin/bash

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

答案 1 :(得分:3)

这不解释为什么会发生这种情况,但会说明如何在新的pid命名空间中正确启动shell:

使用-f标志从unshare

分叉shell
unshare -fp /bin/bash

您还需要传递--mount-proc选项以确保shell在新创建的命名空间中获得PID 1:

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