Linux:-bash: fork: retry: Resource temporarily unavailable
执行命令失败,报错:
原因:
在执行命令 x 过程中有对系统内核提出资源申请,而当前用户占用的某种资源已达到系统限定上限,资源不足。
复现:
当前 Shell 资源限制:
代码:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
void *threadRun(void *arg)
{
sleep(60 * 3);
}
int main()
{
int num = 0;
pthread_t tid;
while (pthread_create(&tid, NULL, threadRun, NULL) == 0)
printf("create thread(%llu) %d OK.\n", tid, ++num);
sleep(60 * 3);
return 0;
}
编译:
[test1280@localhost ~]$ gcc -o main main.c -lpthread
测试:
1.打开两个 Shell 窗口,在其中一个窗口中执行 main 程序,输出如下:
2.在另外一个已打开的窗口中执行非 Shell 内部命令(例如 ls、grep 等),可以观察到:
理由:
上面代码的功能是不断地创建线程,直到创建失败。每个创建的线程都要挂起 3 分钟,以保证同一时刻有大量线程存在。
max user processes(ulimit -u) 的含义为:The maximum number of processes available to a single user.
也就是说,此资源限制某用户同一时刻可以创建的 processes 的数量。
注:
关于 processes 的解释,大部分人解释为“进程”,但实际此处验证可得,用“线程”来解释更为合理:
max user processes 限制某用户同一时刻运行的线程最大数量。
由于 Shell max user processes 的限制,当前用户(test1280)最大同时拥有线程数量上限是 1024。
虽然其他资源充裕,但是不断地申请内核资源创建线程运行,最终达到内核上限。
在另一个 Shell 中执行非内部命令时必将有 fork 调用。
而 fork 调用必将创建一个主线程,由于资源不足无法创建线程进而导致 fork 失败,资源不可达,命令执行失败。
注:
内部命令指的是 pwd、cd 之类的命令,是 Shell 进程本身执行的命令,不必创建新进程。
外部命令(非内部命令)是 ls、grep 之类的命令,是一个可执行文件。
Shell 中执行外部命令,需先 fork 创建子 Shell 进程,然后子 Shell进程中 exec 替换为外部可执行文件,完成命令。
结论:
理论上,ulimit 限制的各类系统资源,当任一资源不足时都可能会导致 fork 调用失败,命令执行失败。
例如:
open files
max memory size
max user processes
……
附录:
如何查看当前用户所拥有的线程数量?
ps -efL | grep test1280 | wc -l
main 程序是在 test1280 账户下运行的,但我的 ps 命令是在 root 账户下执行的,因为 ps 也是外部命令呀!
关于 ulimit 系统资源限制,还请移步参考:
https://blog.csdn.net/test1280/article/details/80465082
^_^