![为什么这个无限循环没有耗尽我的系统资源?](https://linux22.com/image/111397/%E4%B8%BA%E4%BB%80%E4%B9%88%E8%BF%99%E4%B8%AA%E6%97%A0%E9%99%90%E5%BE%AA%E7%8E%AF%E6%B2%A1%E6%9C%89%E8%80%97%E5%B0%BD%E6%88%91%E7%9A%84%E7%B3%BB%E7%BB%9F%E8%B5%84%E6%BA%90%EF%BC%9F.png)
我在 BASH 中执行了以下操作:
while true;do bash;done
我写了这一行,但一开始我不确定它是否:
- 保留在主 shell 中,并在内存或其他东西耗尽时创建尽可能多的子 shell。
- 主 shell 生成一个子 shell,然后该子 shell 生成一个子 shell,直到该谱系耗尽内存或其他内容。
但是,我想这是第二种情况,因为一旦我运行了一个班轮,我在提示回来后不久就开始输入 exit 和另一个 exit 和 exit,exit,exit...但我仍然没有回到主壳。
现在,由于已经打开了这么多子shell,并且每个子shell都是一个程序,所以我认为每个子shell都应该有自己的PID。
所以我做了:
ps aux | grep bash
期望看到很多名称中带有 bash 的进程。
然而,没有这样的,只有两个 bash shell。
怎么可能,我想我对进程、shell、子shell和PID有一个非常错误的想法,但不知道在哪里。
答案1
您的循环在每次迭代中启动一个交互式 shell 会话。
交互式会话会给您一个提示(因为它是交互式的)。退出它会将控制权返回给循环,从而启动另一个交互式 shell。
这就是为什么您不会立即获得大量进程bash
,而只有两个进程,即运行循环的父进程和为您提供新提示的子进程。
循环也可以写成
while true; do bash; done
该true
实用程序不接受参数,它仅返回一个零退出值,该值被 shell 解释为“true”。
如果您想要bash
进程爆炸(所谓的“分叉炸弹”),您可能已经写过
while true; do { bash & }; done
bash
这将在循环的每次迭代中启动一个交互式会话,但作为后台进程。由于会话是作为后台进程启动的,因此循环不会等待最新bash
进程完成后再启动下一个进程。
您可能需要重新启动系统才能恢复。
这个叉子炸弹比它可能的更温和,因为它才刚刚开始一每次迭代中的新流程。其他人很可能以指数方式启动流程。
答案2
您的循环正在启动无数个 shell,但一个接一个,而不是并行的。循环第一次运行时,会运行bash
,这会启动一个新的 shell 并显示提示符。父 shell 等待该 shell 退出;当您键入exit
、退出子 shell 并返回到父 shell 时会发生这种情况,父 shell 再次循环并运行bash
,这将启动一个新 shell 并显示提示...
您可以通过运行来显示您的 shell 级别
echo $SHLVL
当您连续键入命令时,您会发现该数字不会改变exit
。