Linux中每个进程的最大线程数

我写了一个简单的程序来计算一个进程可以在Linux(Centos 5)中的最大线程数。 这里是代码:

int main() { pthread_t thrd[400]; for(int i=0;i<400;i++) { int err=pthread_create(&thrd[i],NULL,thread,(void*)i); if(err!=0) cout << "thread creation failed: " << i <<" error code: " << err << endl; } return 0; } void * thread(void* i) { sleep(100);//make the thread still alive return 0; } 

我发现线程的最大数目只有300! 如果我需要更多的东西呢? 我不得不提到,pthread_create返回12作为错误代码。

谢谢之前

一个Linux的线程限制 ,它可以通过编写/proc/sys/kernel/threads-max所需的限制来修改运行时间。 默认值是从可用的系统内存中计算出来的。 除了这个限制之外,还有另一个限制: /proc/sys/vm/max_map_count ,它限制了最大的mmapped分段,至少最近的内核将mmap每个线程的内存。 如果你碰到它,应该可以安全地增加这个限制。

你碰到限制是在32位操作系统中缺少虚拟内存 。 安装一个64位的Linux,如果你的硬件支持,你会没事的。 我可以轻松地启动30000个线程,堆栈大小为8MB。 该系统有一个单独的Core 2 Duo + 8 GB的系统内存(我在同一时间使用5 GB的其他东西),它运行64位Ubuntu 2.6.32内核。 请注意,必须允许内存过量使用(/ proc / sys / vm / overcommit_memory),否则系统至少需要240 GB的可提交内存(实际内存和交换空间的总和)。

如果你需要很多的线程,并且不能使用64位系统,你唯一的选择就是尽量减少每个线程的内存使用量来节省虚拟内存。 开始请求尽可能少的堆栈。

您的系统限制可能不允许您映射所有需要的线程的堆栈。 看看/proc/sys/vm/max_map_count ,看到这个答案 。 我不是100%确定这是你的问题,因为大多数人在更大的线程数上遇到问题。

当我的线程数量超过某个阈值时,我也遇到了同样的问题。 这是因为在/etc/security/limits.conf中将用户级别限制(用户一次可以运行的进程数量)设置为1024。

所以检查你的/etc/security/limits.conf并寻找条目: –

用户名 – / soft / hard -nproc 1024

将其更改为一些更大的值为100k(需要sudo权限/根),它应该为你工作。

要了解有关安全策略的更多信息,请参阅http://linux.die.net/man/5/limits.conf

用ulimit检查每个线程的堆栈大小,在我的情况下Redhat Linux 2.6:

  ulimit -a ... stack size (kbytes, -s) 10240 

你的每个线程将得到这个数量的内存(10MB)分配给它的堆栈。 有了一个32位的程序和一个4GB的最大地址空间,那最多只有4096MB / 10MB = 409个线程! 减号程序代码,减去堆空间可能会导致您观察到的最大值。 300线程。

你应该可以通过编译一个64位应用程序或者设置ulimit -s 8192甚至ulimit -s 4096来提高这一点。但是,如果这是可取的是另一个讨论…

你会用尽内存,除非你缩小默认的线程堆栈大小。 它在我们的linux版本上是10MB。

编辑:错误代码12 =内存不足,所以我认为1mb堆栈对您来说仍然太大。 编译为32位,我可以得到一个10万个堆栈给我30k线程。 超过30k线程,我得到错误代码11,这意味着没有更多的线程允许。 在错误代码12之前,1MB堆栈给了我大约4k个线程。10MB给了我427个线程。 100MB给我42线程。 1 GB给我4 …我们有64位操作系统64位RAM。 你的操作系统是32位的吗? 当我编译为64位,我可以使用任何我想要的堆栈大小,并获得线程的限制。

另外我注意到,如果我打开netbeans分析的东西(工具|分析),并从IDE运行…我只能得到400线程。 奇怪的。 如果你用完了所有的线程,Netbeans也会死掉。

以下是您可以运行的测试应用程序:

 #include <stdio.h> #include <stdlib.h> #include <pthread.h> #include <signal.h> // this prevents the compiler from reordering code over this COMPILER_BARRIER // this doesnt do anything #define COMPILER_BARRIER() __asm__ __volatile__ ("" ::: "memory") sigset_t _fSigSet; volatile int _cActive = 0; pthread_t thrd[1000000]; void * thread(void *i) { int nSig, cActive; cActive = __sync_fetch_and_add(&_cActive, 1); COMPILER_BARRIER(); // make sure the active count is incremented before sigwait // sigwait is a handy way to sleep a thread and wake it on command sigwait(&_fSigSet, &nSig); //make the thread still alive COMPILER_BARRIER(); // make sure the active count is decrimented after sigwait cActive = __sync_fetch_and_add(&_cActive, -1); //printf("%d(%d) ", i, cActive); return 0; } int main(int argc, char** argv) { pthread_attr_t attr; int cThreadRequest, cThreads, i, err, cActive, cbStack; cbStack = (argc > 1) ? atoi(argv[1]) : 0x100000; cThreadRequest = (argc > 2) ? atoi(argv[2]) : 30000; sigemptyset(&_fSigSet); sigaddset(&_fSigSet, SIGUSR1); sigaddset(&_fSigSet, SIGSEGV); printf("Start\n"); pthread_attr_init(&attr); if ((err = pthread_attr_setstacksize(&attr, cbStack)) != 0) printf("pthread_attr_setstacksize failed: err: %d %s\n", err, strerror(err)); for (i = 0; i < cThreadRequest; i++) { if ((err = pthread_create(&thrd[i], &attr, thread, (void*)i)) != 0) { printf("pthread_create failed on thread %d, error code: %d %s\n", i, err, strerror(err)); break; } } cThreads = i; printf("\n"); // wait for threads to all be created, although we might not wait for // all threads to make it through sigwait while (1) { cActive = _cActive; if (cActive == cThreads) break; printf("Waiting A %d/%d,", cActive, cThreads); sched_yield(); } // wake em all up so they exit for (i = 0; i < cThreads; i++) pthread_kill(thrd[i], SIGUSR1); // wait for them all to exit, although we might be able to exit before // the last thread returns while (1) { cActive = _cActive; if (!cActive) break; printf("Waiting B %d/%d,", cActive, cThreads); sched_yield(); } printf("\nDone. Threads requested: %d. Threads created: %d. StackSize=%lfmb\n", cThreadRequest, cThreads, (double)cbStack/0x100000); return 0; }