浅谈linux下进程最大数、最大线程数、进程打开的文件数
liebian365 2024-11-21 17:35 4 浏览 0 评论
最大进程数目
LINUX中进程的最大理论数计算
- 每个进程都要在全局段描述表GDT中占据两个表项
每个进程的局部段描述表LDT都作为一个独立的段而存在,在全局段描述表GDT中要有一个表项指向这个段的起始地址,并说明该段的长度以及其他一些 参数。除上之外,每个进程还有一个TSS结构(任务状态段)也是一样。所以,每个进程都要在全局段描述表GDT中占据两个表项。
- GDT的容量有多大呢?
段寄存器中用作GDT表下标的位段宽度是13位,所以GDT中可以有213=8192213=8192个描述项。
除一些系统的开销(例如GDT中的第2项和第3项分别用于内核 的代码段和数据段,第4项和第5项永远用于当前进程的代码段和数据段,第1项永远是0,等等)以外,尚有8180个表项可供使用,所以理论上系统中最大的 进程数量是8180/2=40908180/2=4090。
所以系统中理论上最大的进程数是4090
系统中可创建的进程数实际值
linux内核通过进程标识值(process identification value)-PID来标示进程,PID是一个数,类型位pid_t, 实际上就是int类型
为了与老版本的Unix或者Linux兼容,PID的最大值默认设置位32768(short int 短整型的最大值)。
- 查看
可以使用cat /proc/sys/kernel/pid_max来查看系统中可创建的进程数实际值
- 修改
ulimit -u 655351
设置完以后,虽然我们设置户创建进程数的硬限制和软限制都是65535,但是我们还不能使用创建65535个进程
我们在Linux还需要设置内核参数kernel.pid_max,这个参数我默认安装都是32768,
所以即使使用root帐户,却不设置这个内核参数,整个系统最多可以创建的进程数就是32768,所以我们需要进行如下设置:
sysctl -w kernel.pid_max=655351
最大线程数
linux 系统中单个进程的最大线程数有其最大的限制 PTHREAD_THREADS_MAX
这个限制可以在/usr/include/bits/local_lim.h中查看
对 linuxthreads 这个值一般是 1024,对于 nptl 则没有硬性的限制,仅仅受限于系统的资源
这个系统的资源主要就是线程的 stack 所占用的内存,用 ulimit -s 可以查看默认的线程栈大小,一般情况下,这个值是8M=8192KB
可以写一段简单的代码验证最多可以创建多少个线程
include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
void func()
{
}
int main(void)
{
int i = 0;
pthread_t thread;
while ( 1 )
{
if (pthread_create(&thread, NULL, func, NULL) != 0)
{
return;
}
i++;
printf("i = %d\n", i);
}
return EXIT_SUCCESS;
}
试验显示,在我们的系统(Ubuntu-14.04-LTS-64bit)中linuxthreads 上最多可以创建 381 个线程,之后就会返回 EAGAIN
LINUX中单个进程理论上可以创建的最大线程数
而32位系统中,可以穿件381个线程,这个值和理论完全相符,因为 32 位 linux 下的进程用户空间是 3G 的大小,也就是 3072M,用3072M/8M=3843072M/8M=384,但是实际上代码段和数据段等还要占用一些空间,这个值应该向下取整到 383,再减去主线程,得到 382。
那为什么 linuxthreads 上还要少一个线程呢?这可太对了,因为 linuxthreads 还需要一个管理线程
为了突破内存的限制,可以有两种方法
- 用ulimit -s 1024减小默认的栈大小
- 调用pthread_create的时候用pthread_attr_getstacksize设置一个较小的栈大小
要注意的是,即使这样的也无法突破1024 个线程的硬限制,除非重新编译 C 库
最大打开文件数
file-max系统最大打开文件描述符数
/proc/sys/fs/file-max中指定了系统范围内所有进程可打开的文件句柄的数量限制(系统级别, kernel-level).
The value in file-max denotes the maximum number of file handles that the Linux kernel will allocate).
当收到”Too many open files in system”这样的错误消息时, 就应该曾加这个值了.
对于2.2的内核, 还需要考虑inode-max, 一般inode-max设置为file-max的4倍. 对于2.4及以后的内核, 没有inode-max这个文件了.
查看实际值
可以使用cat /proc/sys/fs/file-max来查看当前系统中单进程可打开的文件描述符数目
186405
设置
- 临时性
echo 1000000 > /proc/sys/fs/file-max
- 永久性:在/etc/sysctl.conf中设置
fs.file-max = 1000000
nr_open是单个进程可分配的最大文件数
内核支持的最大file handle数量,即一个进程最多使用的file handle数
the maximum number of files that can be opened by process。
A process cannot use more than NR_OPEN file descriptors.
一个进程不能使用超过NR_OPEN文件描述符。
12
需要C/C++ Linux服务器架构师学习资料私信“资料”(资料包括C/C++,Linux,golang技术,Nginx,ZeroMQ,MySQL,Redis,fastdfs,MongoDB,ZK,流媒体,CDN,P2P,K8S,Docker,TCP/IP,协程,DPDK,ffmpeg等),免费分享
nofile进程最大打开文件描述符数
查看实际值
ulimit -n
当然默认查看的是软资源限制值soft limit,如果想要查看系统硬件所能支持的单进程最大打开文件描述符号的数目,可以使用ulimit -Hn
设置
- 临时性
通过ulimit -Sn设置最大打开文件描述符数的soft limit,注意soft limit不能大于hard limit(ulimit -Hn可查看hard limit)
另外ulimit -n默认查看的是soft limit,但是ulimit -n 1800000则是同时设置soft limit和hard limit。
对于非root用户只能设置比原来小的hard limit。
- 永久性
上面的方法只是临时性的,注销重新登录就失效了,而且不能增大hard limit,只能在hard limit范围内修改soft limit。
若要使修改永久有效,则需要在/etc/security/limits.conf中进行设置(需要root权限),可添加如下两行,表示用户chanon最大打开文件描述符数的soft limit为1800000,hard limit为2000000。以下设置需要注销之后重新登录才能生效:
chanon soft nofile 102400
chanon hard nofile 40960012
设置nofile的hard limit还有一点要注意的就是hard limit不能大于/proc/sys/fs/nr_open,假如hard limit大于nr_open,注销后无法正常登录。
可以修改nr_open的值:
echo 2000000 > /proc/sys/fs/nr_open
file-max, nr_open, onfile之间的关系
针对用户打开最大文件数的限制, 在limits.conf对应的nofile,不管是man手册还是文件中说明都只是一句话
“maximum number of open files”,
它其实对应是单个进程能打开的最大文件数,通常为了省事,我们想取消它的限制
根据man手册中,“values -1, unlimited or infinity indicating no limit”,-1、unlimited、infinity都是表明不做限制
可是当你实际给nofile设置成这个值,等你重启就会发现无法登录系统了。
由此可见,nofile是有一个上限的,同时用ulimit测试:
ulimit -n unlimited1
bash: ulimit: open files: cannot modify limit: 不允许的操作
写一个简单的for循环得出:
for V in `seq 100000 10000000`;do ulimit -n $V;[[ $? != 0 ]]&&break;done1
再执行ulimit -n ,可以看到1048576就是nofile的最大值了,但为什么是这个值?
1024?1024=10485761024?1024=1048576,当然这并没有什么卵用。
再跟踪一下我们就会发现这个值其实是由内核参数nr_open定义的:
cat /proc/sys/fs/nr_open 1
到此我们就要说起nr_open,与file-max了,网上在说到设置最大文件数时偶尔有些帖子也说到要修改file-max,字面上看file-max确实像是对应最大文件数,而在linux内核文档中它们两的解释是:
- file-max:
The value in file-max denotes the maximum number of file-
handles that the Linux kernel will allocate. When you get lots
of error messages about running out of file handles, you might
want to increase this limit
执行:grep -r MemTotal /proc/meminfo | awk ‘{printf(“%d”,$2/10)}’,可以看到与file-max是相近的;
- nr_open:
This denotes the maximum number of file-handles a process can
allocate. Default value is 1024*1024 (1048576) which should be
enough for most machines. Actual limit depends on RLIMIT_NOFILE
resource limit.
file-handles(即文件句柄),然后相比而言在UNIX/LINUX中我们接触更多是file discriptor(FD,即文件描述符),似乎file-handle在windows中是一个类似file discrptor的东东,但是我们讨论的是linux,再google一下,我们可以精确到c语言中这两个概念的区别,
据他们的讨论file-handle应该是一个高层的对象,使用fopen,fread等函数来调用,而FD是底层的一个对象,可以通过open,read等函数来调用。
到此,我们应该可以下一个大致的结论了,file-max是内核可分配的最大文件数,nr_open是单个进程可分配的最大文件数,所以在我们使用ulimit或limits.conf来设置时,如果要超过默认的1048576值时需要先增大nr_open值(sysctl -w fs.nr_open=100000000或者直接写入sysctl.conf文件)。当然百万级别的单进程最大file-handle打开数应该也够用了吧。。
- 所有进程打开的文件描述符数不能超过/proc/sys/fs/file-max
- 单个进程打开的文件描述符数不能超过user limit中nofile的soft limit
- nofile的soft limit不能超过其hard limit
- nofile的hard limit不能超过/proc/sys/fs/nr_open
其他
2.4内核与2.6内核的主要区别
在2.4内核的典型系统上(AS3/RH9),线程是用轻量进程实现的,每个线程要占用一个进程ID,在服务器程序上,如果遇到高点击率访问,会造成进程表溢出,系统为了维护溢出的进程表,会有间歇的暂停服务现象,而2.6内核就不会发生由于大量线程的创建和销毁导致进程表溢出的问题
线程结束必须释放线程堆栈
就是说,线程函数必须调用pthread_exit()结束,否则直到主进程函数退出才释放,特别是2.6内核环境,线程创建速度飞快,一不小心立刻内存被吃光,这一点反倒是2.4内核环境好,因为2.4内核创建的是进程,而且线程创建速度比2.6内核慢几个数量级。特别提醒,在64位CPU,2.6内核创建线程的速度更加疯狂,要是太快的话,加上usleep ()暂停一点点时间比较好
不要编需要锁的线程应用
只有那些不需要互斥量的程序才能最大限度的利用线程编程带来的好处,否则只会更慢,2.6内核是抢占式内核,线程间共享冲突发生的几率远比2.4内核环境高,尤其要注意线程安全,否则就算是单CPU也会发生莫名其妙的内存不同步(CPU的高速缓存和主存内容不一致),Intel的新CPU为了性能使用NUMA架构,在线程编程中一定要注意扬长避短。
单进程服务器最大并发线程数与内存
很有趣,在默认的ulimit参数下,不修改内核头文件
AS3 512M内存最多1000并发持续连接
CentOS4.3 512M内存最多300并发持续连接
似乎是CentOS不如AS3,这里主要原因是ulimit的配置造成,两个系统默认的配置差距很大,要想单进程维持更多线程接收并发连接,就要尽量缩小 ulimit -s的参数,插更多的内存条,单进程服务器上2000并发一点都不难,POSIX默认的限制是每进程64线程,但NTPL并非纯正POSIX,不必理会这个限制,2.6内核下真正的限制是内存条的插槽数目(也许还有买内存的钱数)
最近几天的编程中,注意到在32位x86平台上2.6内核单进程创建最大线程数=VIRT上限/stack,与总内存数关系不大,32位x86系统默认的VIRT上限是3G(内存分配的3G+1G方式),默认 stack大小是10240K,因此单进程创建线程默认上限也就300(3072M / 10240K),用ulimit -s 修改stack到1024K则使上限升到大约3050。我手头没有64位系统,不知道2.6内核在64位上单进程创建线程上限(实际上是本人懒得在同事的机器上装fc4_x86_64)。
前些天买了一套廉价的64位x86系统(64位赛杨+杂牌915主板),安装了CentOS4.3的x86_64版本,跑了一遍下面的小程序,得到的结果是:在ulimit -s 4096的情况下,单进程最大线程数在16000多一点,用top看
VIRT 的上限是64G,也就是36位, cat /proc/cpuinfo的结果是:address sizes : 36 bits physical, 48 bits virtual, 和我想象的标准64位系统不同, 我一直以为64位系统的内存空间也是64位的
附注1
单位里某BSD FANS用AMD64笔记本跑小程序测试线程创建速度(线程创建后立即phread_detach()然后紧跟着pthread_exit(),共计 100万个线程),同样源码OpenBSD竟然比FreeBSD快了3倍,什么时候OpenBSD也变得疯狂起来了?
附注2
测试单进程创建线程上限C源码(test.c)
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
void * thread_null(void);
int main(int argc, char *argv[])
{
unsigned int i;
int rc;
pthread_t pool_id[65536]; //线程ID
sleep(1);
//创建线程
for(i = 0; i < 65536; i++)
{
rc = pthread_create(pool_id + i, 0, (void *)thread_null, NULL);
if (rc != 0)
{
fprintf(stderr, "pthread_create() failure\r\nMax pthread num is %d\r\n", i);
exit(-1);
}
}
fprintf(stdout, "Max pthread num is 65536\r\nYour system is power_full\r\n");
exit(0);
}
void * thread_null(void)
{
pthread_detach(pthread_self());
sleep(60);
pthread_exit(NULL);
}
- 上一篇:C|深入理解输入输出流、文件抽象及相关库函数
- 下一篇:内核地址空间大冒险:系统调用
相关推荐
- 快递查询教程,批量查询物流,一键管理快递
-
作为商家,每天需要查询许许多多的快递单号,面对不同的快递公司,有没有简单一点的物流查询方法呢?小编的回答当然是有的,下面随小编一起来试试这个新技巧。需要哪些工具?安装一个快递批量查询高手快递单号怎么快...
- 一键自动查询所有快递的物流信息 支持圆通、韵达等多家快递
-
对于各位商家来说拥有一个好的快递软件,能够有效的提高自己的工作效率,在管理快递单号的时候都需要对单号进行表格整理,那怎么样能够快速的查询所有单号信息,并自动生成表格呢?1、其实方法很简单,我们不需要一...
- 快递查询单号查询,怎么查物流到哪了
-
输入单号怎么查快递到哪里去了呢?今天小编给大家分享一个新的技巧,它支持多家快递,一次能查询多个单号物流,还可对查询到的物流进行分析、筛选以及导出,下面一起来试试。需要哪些工具?安装一个快递批量查询高手...
- 3分钟查询物流,教你一键批量查询全部物流信息
-
很多朋友在问,如何在短时间内把单号的物流信息查询出来,查询完成后筛选已签收件、筛选未签收件,今天小编就分享一款物流查询神器,感兴趣的朋友接着往下看。第一步,运行【快递批量查询高手】在主界面中点击【添...
- 快递单号查询,一次性查询全部物流信息
-
现在各种快递的查询方式,各有各的好,各有各的劣,总的来说,还是有比较方便的。今天小编就给大家分享一个新的技巧,支持多家快递,一次能查询多个单号的物流,还能对查询到的物流进行分析、筛选以及导出,下面一起...
- 快递查询工具,批量查询多个快递快递单号的物流状态、签收时间
-
最近有朋友在问,怎么快速查询单号的物流信息呢?除了官网,还有没有更简单的方法呢?小编的回答当然是有的,下面一起来看看。需要哪些工具?安装一个快递批量查询高手多个京东的快递单号怎么快速查询?进入快递批量...
- 快递查询软件,自动识别查询快递单号查询方法
-
当你拥有多个快递单号的时候,该如何快速查询物流信息?比如单号没有快递公司时,又该如何自动识别再去查询呢?不知道如何操作的宝贝们,下面随小编一起来试试。需要哪些工具?安装一个快递批量查询高手快递单号若干...
- 教你怎样查询快递查询单号并保存物流信息
-
商家发货,快递揽收后,一般会直接手动复制到官网上一个个查询物流,那么久而久之,就会觉得查询变得特别繁琐,今天小编给大家分享一个新的技巧,下面一起来试试。教程之前,我们来预览一下用快递批量查询高手...
- 简单几步骤查询所有快递物流信息
-
在高峰期订单量大的时候,可能需要一双手当十双手去查询快递物流,但是由于逐一去查询,效率极低,追踪困难。那么今天小编给大家分享一个新的技巧,一次能查询多个快递单号的物流,下面一起来学习一下,希望能给大家...
- 物流单号查询,如何查询快递信息,按最后更新时间搜索需要的单号
-
最近有很多朋友在问,如何通过快递单号查询物流信息,并按最后更新时间搜索出需要的单号呢?下面随小编一起来试试吧。需要哪些工具?安装一个快递批量查询高手快递单号若干怎么快速查询?运行【快递批量查询高手】...
- 连续保存新单号功能解析,导入单号查询并自动识别批量查快递信息
-
快递查询已经成为我们日常生活中不可或缺的一部分。然而,面对海量的快递单号,如何高效、准确地查询每一个快递的物流信息,成为了许多人头疼的问题。幸运的是,随着科技的进步,一款名为“快递批量查询高手”的软件...
- 快递查询教程,快递单号查询,筛选更新量为1的单号
-
最近有很多朋友在问,怎么快速查询快递单号的物流,并筛选出更新量为1的单号呢?今天小编给大家分享一个新方法,一起来试试吧。需要哪些工具?安装一个快递批量查询高手多个快递单号怎么快速查询?运行【快递批量查...
- 掌握批量查询快递动态的技巧,一键查找无信息记录的两种方法解析
-
在快节奏的商业环境中,高效的物流查询是确保业务顺畅运行的关键。作为快递查询达人,我深知时间的宝贵,因此,今天我将向大家介绍一款强大的工具——快递批量查询高手软件。这款软件能够帮助你批量查询快递动态,一...
- 从复杂到简单的单号查询,一键清除单号中的符号并批量查快递信息
-
在繁忙的商务与日常生活中,快递查询已成为不可或缺的一环。然而,面对海量的单号,逐一查询不仅耗时费力,还容易出错。现在,有了快递批量查询高手软件,一切变得简单明了。只需一键,即可搞定单号查询,一键处理单...
- 物流单号查询,在哪里查询快递
-
如果在快递单号多的情况,你还在一个个复制粘贴到官网上手动查询,是一件非常麻烦的事情。于是乎今天小编给大家分享一个新的技巧,下面一起来试试。需要哪些工具?安装一个快递批量查询高手快递单号怎么快速查询?...
你 发表评论:
欢迎- 一周热门
- 最近发表
- 标签列表
-
- wireshark怎么抓包 (75)
- qt sleep (64)
- cs1.6指令代码大全 (55)
- factory-method (60)
- sqlite3_bind_blob (52)
- hibernate update (63)
- c++ base64 (70)
- nc 命令 (52)
- wm_close (51)
- epollin (51)
- sqlca.sqlcode (57)
- lua ipairs (60)
- tv_usec (64)
- 命令行进入文件夹 (53)
- postgresql array (57)
- statfs函数 (57)
- .project文件 (54)
- lua require (56)
- for_each (67)
- c#工厂模式 (57)
- wxsqlite3 (66)
- dmesg -c (58)
- fopen参数 (53)
- tar -zxvf -c (55)
- 速递查询 (52)