Linux 上的最大 children 进程数
Maximum number of children processes on Linux
下面的代码将生成尽可能多的 children。他们自己不会进一步分叉,一旦 parent 进程退出就会变成僵尸。
parent 进程会产生多少 children 个进程?
int main(int argc, char *arg[])
{
while(fork() > 0);
}
更新 -- 我可能太快了,没有看到没有 fork 循环。那么这可能取决于在那台机器上分叉的成本。僵尸也可能使用系统资源,这些资源在某个时候会被耗尽。而下面提到的ulimit命令当然仍然有效--
更新 2:我在 some copy of /linux/kernel/fork.c 中看到了这一点,它应该使机器可用(max_threads 显然也限制了进程的数量,因为每个进程至少有一个线程):
/*
272 * The default maximum number of threads is set to a safe
273 * value: the thread structures can take up at most half
274 * of memory.
275 */
276 max_threads = mempages / (8 * THREAD_SIZE / PAGE_SIZE);
--
原答案:
它将创建物理上可能的尽可能多的进程(也就是说,它会迅速冻结机器——我已经这样做了),或者为当前用户或 shell 允许的尽可能多的进程,如果施加这样的限制。在 bash 中,可以通过内置 shell 命令 ulimit -u <number>
施加限制。请注意,进程可能不必通过 bash 启动(也许 cron 作业不会)。
可以使用 setrlimit(2) using RLIMIT_NPROC
. Notice that fork(2) can fail for several reasons. You could use bash
builtin ulimit
来限制子进程的数量。
您可以使用 getrlimit
(或解析 /proc/self/limits
,请参阅 proc(5))来获取该信息。
系统范围内,您可以使用 /proc/sys/kernel/threads-max
,因为:
This file specifies the system-wide limit on the number of threads
(tasks) that can be created on the system.
还有/proc/sys/kernel/pid_max
This file specifies the value at which PIDs wrap around (i.e., the
value in this file is one greater than the maximum PID). PIDs
greater than this value are not allocated; thus, the value in this
file also acts as a system-wide limit on the total number of
processes and threads. The default value for this file, 32768,
results in the same range of PIDs as on earlier kernels. On 32-bit
platforms, 32768 is the maximum value for pid_max. On 64-bit
systems, pid_max can be set to any value up to 2^22 (PID_MAX_LIMIT,
approximately 4 million).
但是,可能还有其他限制(特别是交换 space)。
内核的任务要么是单线程进程,要么是某个进程中的某个线程 - 例如由低级系统调用 clone(2) (or some kernel thread 创建,如 kworker
、ksoftirqd
等...)。
顺便说一句,实际进程数受可用资源的限制要大得多。一个典型的 Linux 桌面只有几百个(现在,我的 Debian/x86-64 桌面有 32Gb 内存和 i5-4690S 有 227 个进程)。所以一个进程是一个非常昂贵的资源(它需要 RAM,它需要 CPU...)。如果它们太多,您将遇到 thrashing. And in practice, you don't want to have too many runnable processes or schedulable tasks (probably only a few dozens of them at most, perhaps no more than a few per core)。
以防万一,除了答案,Linux内核5.18是这样的:
// ...
/*
* The rest of the robust-futex field is for the TID:
*/
#define FUTEX_TID_MASK 0x3fffffff
// ...
// ...
#include <linux/futex.h>
// ...
/*
* Minimum number of threads to boot the kernel
*/
#define MIN_THREADS 20
/*
* Maximum number of threads
*/
#define MAX_THREADS FUTEX_TID_MASK
// ...
static int max_threads; /* tunable limit on nr_threads */
// ...
/*
* set_max_threads
*/
static void set_max_threads(unsigned int max_threads_suggested)
{
// ...
max_threads = clamp_t(u64, threads, MIN_THREADS, MAX_THREADS);
}
// ...
void __init fork_init(void)
{
// ...
set_max_threads(MAX_THREADS);
// ...
}
// ...
/*
* This creates a new process as a copy of the old one,
* but does not actually start it yet.
*
* It copies the registers, and all the appropriate
* parts of the process environment (as per the clone
* flags). The actual kick-off is left to the caller.
*/
static __latent_entropy struct task_struct *copy_process(
// ...
)
{
// ...
/*
* If multiple threads are within copy_process(), then this check
* triggers too late. This doesn't hurt, the check is only there
* to stop root fork bombs.
*/
retval = -EAGAIN;
if (data_race(nr_threads >= max_threads))
goto bad_fork_cleanup_count;
// ...
}
//...
关于“TID
”:
gettid() returns the caller's thread ID (TID). In a single-threaded process, the thread ID is equal to the process ID (PID, as returned by getpid(2)).
下面的代码将生成尽可能多的 children。他们自己不会进一步分叉,一旦 parent 进程退出就会变成僵尸。
parent 进程会产生多少 children 个进程?
int main(int argc, char *arg[])
{
while(fork() > 0);
}
更新 -- 我可能太快了,没有看到没有 fork 循环。那么这可能取决于在那台机器上分叉的成本。僵尸也可能使用系统资源,这些资源在某个时候会被耗尽。而下面提到的ulimit命令当然仍然有效--
更新 2:我在 some copy of /linux/kernel/fork.c 中看到了这一点,它应该使机器可用(max_threads 显然也限制了进程的数量,因为每个进程至少有一个线程):
/*
272 * The default maximum number of threads is set to a safe
273 * value: the thread structures can take up at most half
274 * of memory.
275 */
276 max_threads = mempages / (8 * THREAD_SIZE / PAGE_SIZE);
-- 原答案:
它将创建物理上可能的尽可能多的进程(也就是说,它会迅速冻结机器——我已经这样做了),或者为当前用户或 shell 允许的尽可能多的进程,如果施加这样的限制。在 bash 中,可以通过内置 shell 命令 ulimit -u <number>
施加限制。请注意,进程可能不必通过 bash 启动(也许 cron 作业不会)。
可以使用 setrlimit(2) using RLIMIT_NPROC
. Notice that fork(2) can fail for several reasons. You could use bash
builtin ulimit
来限制子进程的数量。
您可以使用 getrlimit
(或解析 /proc/self/limits
,请参阅 proc(5))来获取该信息。
系统范围内,您可以使用 /proc/sys/kernel/threads-max
,因为:
This file specifies the system-wide limit on the number of threads (tasks) that can be created on the system.
还有/proc/sys/kernel/pid_max
This file specifies the value at which PIDs wrap around (i.e., the value in this file is one greater than the maximum PID). PIDs greater than this value are not allocated; thus, the value in this file also acts as a system-wide limit on the total number of processes and threads. The default value for this file, 32768, results in the same range of PIDs as on earlier kernels. On 32-bit platforms, 32768 is the maximum value for pid_max. On 64-bit systems, pid_max can be set to any value up to 2^22 (PID_MAX_LIMIT, approximately 4 million).
但是,可能还有其他限制(特别是交换 space)。
内核的任务要么是单线程进程,要么是某个进程中的某个线程 - 例如由低级系统调用 clone(2) (or some kernel thread 创建,如 kworker
、ksoftirqd
等...)。
顺便说一句,实际进程数受可用资源的限制要大得多。一个典型的 Linux 桌面只有几百个(现在,我的 Debian/x86-64 桌面有 32Gb 内存和 i5-4690S 有 227 个进程)。所以一个进程是一个非常昂贵的资源(它需要 RAM,它需要 CPU...)。如果它们太多,您将遇到 thrashing. And in practice, you don't want to have too many runnable processes or schedulable tasks (probably only a few dozens of them at most, perhaps no more than a few per core)。
以防万一,除了
// ...
/*
* The rest of the robust-futex field is for the TID:
*/
#define FUTEX_TID_MASK 0x3fffffff
// ...
// ...
#include <linux/futex.h>
// ...
/*
* Minimum number of threads to boot the kernel
*/
#define MIN_THREADS 20
/*
* Maximum number of threads
*/
#define MAX_THREADS FUTEX_TID_MASK
// ...
static int max_threads; /* tunable limit on nr_threads */
// ...
/*
* set_max_threads
*/
static void set_max_threads(unsigned int max_threads_suggested)
{
// ...
max_threads = clamp_t(u64, threads, MIN_THREADS, MAX_THREADS);
}
// ...
void __init fork_init(void)
{
// ...
set_max_threads(MAX_THREADS);
// ...
}
// ...
/*
* This creates a new process as a copy of the old one,
* but does not actually start it yet.
*
* It copies the registers, and all the appropriate
* parts of the process environment (as per the clone
* flags). The actual kick-off is left to the caller.
*/
static __latent_entropy struct task_struct *copy_process(
// ...
)
{
// ...
/*
* If multiple threads are within copy_process(), then this check
* triggers too late. This doesn't hurt, the check is only there
* to stop root fork bombs.
*/
retval = -EAGAIN;
if (data_race(nr_threads >= max_threads))
goto bad_fork_cleanup_count;
// ...
}
//...
关于“TID
”:
gettid() returns the caller's thread ID (TID). In a single-threaded process, the thread ID is equal to the process ID (PID, as returned by getpid(2)).