【问题标题】:unshare --pid /bin/bash - fork cannot allocate memoryunshare --pid /bin/bash - fork 不能分配内存
【发布时间】:2017-11-23 19:16:18
【问题描述】:

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

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

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

从那里运行 ls 会产生核心转储。退出是唯一可能的事情。

为什么要这么做?

【问题讨论】:

    标签: linux bash linux-namespaces


    【解决方案1】:

    这并没有解释为什么会发生这种情况,而是说明如何在新的 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
    

    【讨论】:

    • 很高兴看到它有帮助!
    【解决方案2】:

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

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

    取消共享 -p /bin/bash

    unshare进程会执行/bin/bash,/bin/bash会fork几个子进程,bash的第一个子进程会成为新命名空间的PID 1,子进程完成任务后退出.所以新命名空间的PID 1就退出了。

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

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

    取消共享 -fp /bin/bash

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

    【讨论】:

    • 用一些手册页引用来支持这个非常有用的答案:man 2 unshare 说关于CLONE_NEWPID取消共享 PID 命名空间,以便调用进程为其拥有一个新的 PID 命名空间不与任何先前存在的进程共享的子进程。调用进程不会移动到新的命名空间中。 调用进程创建的第一个子进程的进程 ID 为 1,并将承担新命名空间中的 init(1) 角色。
    • " 这是linux内核想要的行为:进程A创建一个新的命名空间,进程A本身不会被放入新的命名空间,只会放入进程A的子进程进入新的命名空间。” --- 这个语句 Trie 不是只针对 PID 命名空间吗?它不能与 mount 等其他命名空间一起使用吗?
    • @yupeng0921 "unshare -fp /bin/bash",它起作用了。但在那之后当我做ps -e 时,我可以看到来自主机的所有进程。根据解释,我应该只看到 PID 1 的 unshare 进程和一些 bash 进程正在运行。但这种情况并非如此。你能解释一下吗?
    猜你喜欢
    • 2017-09-24
    • 1970-01-01
    • 2013-09-25
    • 2018-01-29
    • 2017-04-12
    • 2015-04-27
    • 2015-08-17
    • 2013-03-04
    • 1970-01-01
    相关资源
    最近更新 更多