################################################################################
进程最大线程数研究
################################################################################
1. 测试代码(64位机器, centos)
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <sys/types.h>
#include <sys/syscall.h>
//gettid 需要直接调用syscall, 请查阅man gettid ,
//新libc已经有gettid 函数了, 所以该宏可以删除,保留可兼容旧版本
#ifndef gettid
#define gettid() syscall(SYS_gettid)
#endif
int i_index=0;
void *foo(void *param)
{
int ind=(int)(long)param;
int var=0;
// printf("param:%p\n",param);
if(ind==0 ||ind==1||ind==2||ind==30000)
{
printf("ind:%d, stack neer %p\n",ind,&var);
printf("tid is %ld\n",gettid());
}
while(1)
{
sleep(1);
}
}
int main()
{
int ret;
pthread_t id;
while(1)
{
ret = pthread_create(&id, NULL, foo, (void *)(long)i_index);
if(ret !=0)
{
perror("reason:");
break;
}
i_index++;
if(i_index==50) break; //如果不研究最大个数,就在50线程时退出吧
}
printf("the %d threads created!\n", i_index);
printf("press a key to exit!\n");
getchar();
return 0;
}
上述代码的执行:结果:
$ ./test_thread
ind:0, stack neer 0x7f62f121aee0
tid is 70020
ind:1, stack neer 0x7f62f0a19ee0
tid is 70021
ind:2, stack neer 0x7f62f0218ee0
tid is 70022
the 50 threads created!
press a key to exit!
我们看到,一个线程堆栈就占据了, 0x7f62f121aee0-0x7f62f0a19ee0=0x801000 大小.
------------------------------------------------------------
root 用户可以创建更多的线程数
------------------------------------------------------------
用户空间下:
[hjj@hjj /home/testapp]$ ./threadcreatenum
reason:: Resource temporarily unavailable
the 10141 threads created!
press a key to exit!
root 空间下:
root@hjj /home/testapp]# ./threadcreatenum
reason:: Resource temporarily unavailable
the 29114 threads created!
press a key to exit!
看来用户空间还是受到了一些限制, 应该用root 用户。
那么root 用户还受到什么限制呢?
------------------------------------------------------------
root 用户线程数受限与系统配置
------------------------------------------------------------
[root@hjj /home/testapp]# cat /proc/sys/kernel/threads-max
29413
或用如下命令:
[root@hjj /home/samba/testapp]# sysctl -a |grep threads
kernel.threads-max = 29413
[root@hjj /home/testapp]# echo 50000 >/proc/sys/kernel/threads-max
[root@hjj /home/testapp]# cat /proc/sys/kernel/threads-max
50000
[root@hjj /home/testapp]# ./threadcreatenum
reason:: Cannot allocate memory
the 32223 threads created!
press a key to exit!
[hjj@hjj /home/testapp]$ ulimit -s
8192
8M * 3w 线程,将耗费200多G 的虚拟内存
为了增加直感,修改程序使打印堆栈地址。如下:
[root@hjj /home/testapp]# ./threadcreatenum
stack neer 0x7f6ab71b1e8c
stack neer 0x7f6ab69b0e8c
the 30000 threads created!
stack neer 0x7f3018482e8c
reason:: Cannot allocate memory
the 32223 threads created!
press a key to exit!
由此看出,每线程堆栈 0x801000 大小。
第30000 线程,已经占据3axxxxxxxx个内存 58*4G内存
而此时观察内存
[hjj@hjj /home/testapp]$ free -m
total used free shared buffers cached
Mem: 1858 1596 261 0 45 266
-/+ buffers/cache: 1284 574
Swap: 3999 0 3999
释放掉程序,内存如下:
[hjj@hjj /home/testapp]$ free -m
total used free shared buffers cached
Mem: 1858 623 1235 0 45 266
-/+ buffers/cache: 310 1547
Swap: 3999 0 3999
操作系统只占用了900M-1G物理内存,模拟了240G 虚拟内存。可见,操作系统为我们隐藏了一些东西!
当报资源不够时,是系统限制。
当报内存不够时,是系统真没有那么多了。系统不可能把所有内存都分给应用
------------------------------------------------------------
线程个数由系统管理,将程序堆栈减小或增加,并不能改变线程的个数.
------------------------------------------------------------
[root@hjj /home/testapp]# ulimit -s 1024
ot@hjj /home/testapp]# ./threadcreatenum
stack neer 0x7fcc5c342e8c
stack neer 0x7fcc5c241e8c
stack neer 0x7fc501f13e8c
reason:: Cannot allocate memory
the 32220 threads created!
press a key to exit!
可见线程数与原来一样。 差3个是因为系统每次运行,堆栈位置会变化。不足为虑。
虽然pthread_create 返回了pthread_t* 但它是透明的, 它隐藏了线程的细节! 你仅能看到一个long int 变量. 其它什么也看不到了. (包括线程名称,线程id 等都看不见)
/* Thread identifiers. The structure of the attribute type is not
exposed on purpose. */
typedef unsigned long int pthread_t;