[英]Maximum number of children processes on Linux
下面的代碼將產生盡可能多的孩子。 自己不會進一步fork,一旦父進程退出就會變成僵屍。
父進程會生成多少個子進程?
int main(int argc, char *arg[])
{
while(fork() > 0);
}
可以使用RLIMIT_NPROC
通過setrlimit(2)限制子進程的數量。 請注意, fork(2)可能由於多種原因而失敗。 您可以使用bash
內置的 ulimit
來設置該限制。
您可以使用getrlimit
(或解析/proc/self/limits
,請參閱proc(5) )來獲取該信息。
在整個系統范圍內,您可能會使用/proc/sys/kernel/threads-max
因為:
該文件指定了系統范圍內可以在系統上創建的線程(任務)數量的限制。
還有/proc/sys/kernel/pid_max
該文件指定PID環繞的值(即,該文件中的值比最大PID大1)。 大於此值的PID不會分配; 因此,此文件中的值還充當系統范圍內進程和線程總數的限制。 該文件的默認值32768導致PID范圍與早期內核相同。 在32位平台上,pid_max的最大值為32768。 在64位系統上,可以將pid_max設置為2到22之間的任何值(PID_MAX_LIMIT,大約為400萬)。
但是,可能還有其他限制(尤其是交換空間)。
內核的任務要么是單線程進程,要么是某個進程中的某個線程-例如,由低級syscall clone(2)創建 (或某些內核線程,如kworker
, ksoftirqd
等)。
順便說一句,實際的過程數量更多地受到可用資源的限制。 一個典型的Linux桌面只有幾百個(現在,我的帶有32Gb RAM和i5-4690S的Debian / x86-64桌面有227個進程)。 因此,進程是一個非常昂貴的資源(它需要RAM,它需要CPU ...)。 如果它們太多,就會發生抖動 。 而且在實踐中,您不希望有太多可運行的進程或可調度的任務(最多可能只有幾十個,每個內核最多不超過幾個)。
更新-我也許很快,沒有看到沒有派生循環。 然后,這可能取決於在該計算機上進行分叉的價格。 僵屍還可能使用系統資源,這些資源有時會耗盡。 而且下面提到的ulimit命令當然仍然有效-
更新2:我在/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作業)。
為了以防萬一,除了@Peter - Reinstate Monica answer,Linux kernel 5.18 是這樣的:
// ...
/*
* The rest of the robust-futex field is for the TID:
*/
#define FUTEX_TID_MASK 0x3fffffff
// ...
/內核/fork.c :
// ...
#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() 返回調用者的線程 ID (TID)。 在單線程進程中,線程 ID 等於進程 ID(PID,由 getpid(2) 返回)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.