最近我一直在挖掘有关 GNU/Linux 中进程的信息,并且遇到了臭名昭著的 fork 炸弹:
:(){ : | :& }; :
理论上,它应该无限复制自己,直到系统耗尽资源......
但是,我已经尝试在CLI Debian和GUI Mint发行版上进行测试,它似乎对系统没有太大影响。是的,有很多进程被创建,过了一会儿我读到了控制台消息,比如:
bash:fork:资源暂时不可用
bash:fork:重试:没有子进程
但一段时间后,所有进程都会被杀死,一切都恢复正常。我已经读过ulimit为每个用户设置了最大进程数,但我似乎无法将它提高到很远。
针对叉形炸弹的系统保护措施是什么?为什么它不会自我复制,直到一切都冻结或至少滞后很多?有没有办法用叉子炸弹真正使系统崩溃?
您可能有一个使用 systemd 的 Linux 发行版。
Systemd 为每个用户创建一个 cgroup,一个用户的所有进程都属于同一个 cgroup。
Cgroups 是一种 Linux 机制,用于设置系统资源的限制,例如最大进程数、CPU 周期、RAM 使用量等。这是一个不同的、更现代的资源限制层
ulimit
(它使用getrlimit()
系统调用)。如果您运行
systemctl status user-<uid>.slice
(代表用户的 cgroup),您可以看到该 cgroup 中允许的当前和最大任务数(进程和线程)。默认情况下,systemd 允许每个用户的最大任务数是“系统范围最大值”(
sysctl kernel.threads-max
)的 33%;这通常相当于约 10,000 个任务。如果要更改此限制:在 systemd v239 及更高版本中,用户默认设置通过TasksMax=在:
要调整特定用户的限制(将立即应用并存储在 /etc/systemd/system.control 中),请运行:
覆盖单元设置的常用机制(例如
systemctl edit
)也可以在此处使用,但它们需要重新启动。例如,如果您想更改每个用户的限制,您可以创建/etc/systemd/system/user-.slice.d/15-limits.conf
.在 systemd v238 及更早版本中,用户默认值是通过UserTasksMax= in设置的
/etc/systemd/logind.conf
。更改值通常需要重新启动。有关此的更多信息:
无论如何,这不会使现代 Linux 系统崩溃。
它会创建大量进程,但不会在进程空闲时真正消耗那么多 CPU。现在,您在用完 RAM 之前用完了进程表中的插槽。
如果您没有像 Hkoof 指出的那样受到 cgroup 限制,那么以下更改仍然会导致系统崩溃:
回到 90 年代,我不小心在自己身上释放了其中一个。我无意中在包含 fork() 命令的 C 源文件上设置了执行位。当我双击它时,csh 尝试运行它,而不是像我想要的那样在编辑器中打开它。
即使那样,它也没有使系统崩溃。Unix 足够强大,您的帐户和/或操作系统会有进程限制。相反,它变得非常缓慢,任何需要启动进程的东西都可能失败。
幕后发生的事情是进程表填满了试图创建新进程的进程。如果其中一个终止(由于进程表已满而导致 fork 出现错误,或者由于绝望的操作员试图恢复其系统的健全性),其他进程之一将愉快地分叉一个新进程来填充虚空。
“叉子炸弹”基本上是一个无意中自我修复的进程系统,其任务是让您的进程表保持完整。阻止它的唯一方法就是以某种方式一次杀死他们。