簡體   English   中英

Linux 上的最大子進程數

[英]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)創建 (或某些內核線程,kworkerksoftirqd等)。

順便說一句,實際的過程數量更多地受到可用資源的限制。 一個典型的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 是這樣的:

/include/uapi/linux/futex.h :

// ...

/*
 * 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) 返回)。

來源: https://man7.org/linux/man-pages/man2/gettid.2.html

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM