我正在尝试使用linux命名空间。特别是pid命名空间。
我以为我用bash测试了一些东西但遇到了这个问题:
unshare -p /bin/bash
bash: fork: Cannot allocate memory
从那里运行ls给了一个核心转储。退出是唯一可能的事情。
为什么这样做?
答案 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
:
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