当使用unshare -p命令时,出现如下报错:
unshare -p /bin/bash
bash: fork: Cannot allocate memory
如果想要正常使用,只需要添加–fork选项就行
unshare -p --fork /bin/bash
在使用 unshare -p
创建新的 PID 命名空间时,存在一些关键的特性和限制。
PID 命名空间的工作原理
- PID 1 的特殊性:
- 在每个 PID 命名空间中,第一个启动的进程总是 PID 1。这个进程具有特殊的管理职责,比如处理僵尸进程和信号。
- PID 1 需要能够创建新的进程和管理系统资源。如果没有正确的上下文,其他进程(如 Bash)将无法正常运行。
- 使用
--fork
的必要性:- 当你使用
unshare -p
而不加--fork
时,新的命名空间中的进程实际上是在当前进程中启动的,而这个进程仍然保持其原有的 PID,这意味着它不是真正的 PID 1。 - 这会导致 Bash 或其他进程无法获得 PID 1 所需的特权,从而导致无法管理进程,可能出现问题。
- 当你使用
- 解决方案:
- 加上
--fork
选项可以确保新创建的进程在新的 PID 命名空间中运行,成为真正的 PID 1,从而能够正确处理进程管理和资源分配。 - 这样可以确保 Bash 及其他进程能够正常运行并处理其职责。
- 加上
形象理解
-
不采用–fork直接隔离pid
/bin/bash
直接隔离pid,在新的命名空间中运行的bash程序
-
采用–fork,由子进程使用unshare来隔离pid
unshare -p --fork --mount-proc /bin/bash
unshare先创建子进程,然后将传入的参数输入,创建bash程序
-
两者的区别在于新的命名空间一个是由
原始的bash
创建的,一个是由unshare进程创建的
。 -
由于/bin/bash中第一个传入的进程(PID=1)是调用他们的进程(即管理进程),所以1中
bash
成为了管理进程,2中unshare
成为了管理进程。而原始的bash进程
管理不了这个新的命名空间,所以就会报错。 -
注意!!如果认为fork没有用的话,那么290705这个进程在fork后就要被kill掉了,所以这个进程的存在就是为了管理子进程
-
为什么别的选项不需要fork(如-i)?这是因为他们并没有隔离自己的PID,所以他们都被管理原始bash的进程管理着,不需要新的管理者
父进程(父bash)、子进程(unshare创建的bash)之间的关系
(这里统一称为父进程和子进程)如果进一步实验就会发现:
-
父进程和子进程都可以看到对方运行的进程
- 因为父进程和子进程并没有使用
--mount-proc
选项(没有隔离进程信息),由于linux运行任何一个进程都会创建一个对应的文件,所以他们查看进程的状况时看到的都是同一堆进程文件,自然就能看到对方运行的进程
- 因为父进程和子进程并没有使用
-
父进程可以杀掉子进程中运行的进程,而子进程却杀不掉父进程中运行的进程
- 子进程是父进程创建的,在设计中父进程的权限要大于子进程,所以父进程可以kill掉子进程中的进程,相反子进程权限不足