我在新启动的 bash 中运行以下命令(没有任何先前的子进程)
$ prlimit --pid $BASHPID --nproc=20:
Run Code Online (Sandbox Code Playgroud)
这给了我一个雪崩
bash: fork: retry: No child processes
bash: fork: retry: No child processes
bash: fork: retry: No child processes
bash: fork: retry: No child processes
bash: fork: Resource temporarily unavailable
Run Code Online (Sandbox Code Playgroud)
我想知道 20 是一个数字,还是程序错误?这里发生了什么?
我知道 bash 有一个内部内置ulimit调用,但为什么prlimit不起作用
bash 内置也ulimit产生相同的结果
$ ulimit -Su 20
bash: fork: retry: No child processes
bash: fork: retry: No child processes
bash: fork: retry: No child processes
bash: fork: retry: No child processes
bash: fork: Resource temporarily unavailable
bash: wait_for: No record of process 7527
bash: fork: retry: No child processes
bash: fork: retry: No child processes
Run Code Online (Sandbox Code Playgroud)
这个问题的答案可能与如何理解 ulimit RLIMIT_NPROC 有关。它似乎既是 UID 又是 PID 绑定?
也许有人也能够深入了解两种不同的错误消息的区别No child processes和Resource temporarily unavailable
您误解了进程限制的工作原理。prlimit --nprocaka RLIMIT_NPROCakaulimit -u是整个用户的最大进程数¹。如果您已经有 20 个正在运行的进程,并且您将限制设置为 20,则无法创建任何新进程。重要的是有多少进程以您的用户身份运行,无论他们的父母是谁或他们的限制设置是什么都无关紧要。
微妙之处在于,虽然限制是全局的,但它仅适用于设置了它的进程。因此,如果您有 18 个进程在运行,并且prlimit --nproc 20 bash在一个终端和prlimit --nproc 30 bash另一个终端中运行,则第一个 bash 无法创建任何子进程,但第二个可以创建更多子进程,直到总共有 30 个(无论它们是否已启动)是否来自那个bash)。
如果您将某个进程的限制设置为 1,则该进程根本无法分叉,但其他进程仍然可以分叉。如果您在登录脚本中将限制设置为一个数字,则该数字适用于您的进程(除了那些在未读取登录脚本的情况下启动的进程,例如从 cron 作业)。其他情况可能会令人困惑。
从实现的角度来描述这一点是最容易的。该限制仅在执行fork系统调用时读取¹。当一个进程调用 时fork,内核会计算以同一用户身份运行的进程数R。如果调用进程的 NPROC 限制小于或等于R,则调用将被拒绝并显示错误EAGAIN(“资源暂时不可用”,即“再试一次”)。
在您的情况下,您可能已经有至少 20 个进程在运行,并且您.bashrc运行了多个子进程(或者更确切地说,由于已达到进程限制而无法运行它们)。
您会看到两条不同的消息,因为当错误为EAGAIN. 第一次它显示一条消息说它正在重试,最后它显示一条消息说它已放弃。
¹更准确地说,是内核线程。
²这个系统调用clone在 Linux 上被调用。