ulimit用于shell启动进程所占用的资源,能够用来设置系统的限制html
语法格式node
ulimit [-acdfHlmnpsStvw] [size]linux
在/etc/security/limits.conf
文件中定义
限制。shell
命令参数 | 描述 | 例子 |
---|---|---|
-H | 设置硬资源限制,一旦设置不能增长。 | ulimit – Hs 64;限制硬资源,线程栈大小为 64K。 |
-S | 设置软资源限制,设置后能够增长,可是不能超过硬资源设置。 | ulimit – Sn 32;限制软资源,32 个文件描述符。 |
-a | 显示当前全部的 limit 信息 | ulimit – a;显示当前全部的 limit 信息 |
-c | 最大的 core 文件的大小, 以 blocks 为单位 | ulimit – c unlimited; 对生成的 core 文件的大小不进行限制 |
-d | 进程最大的数据段的大小,以 Kbytes 为单位 | ulimit -d unlimited;对进程的数据段大小不进行限制 |
-f | 进程能够建立文件的最大值,以 blocks 为单位 | ulimit – f 2048;限制进程能够建立的最大文件大小为 2048 blocks |
-l | 最大可加锁内存大小,以 Kbytes 为单位 | ulimit – l 32;限制最大可加锁内存大小为 32 Kbytes |
-m | 最大内存大小,以 Kbytes 为单位 | ulimit – m unlimited;对最大内存不进行限制 |
-n | 能够打开最大文件描述符的数量 | ulimit – n 128;限制最大可使用 128 个文件描述符 |
-p | 管道缓冲区的大小,以 Kbytes 为单位 | ulimit – p 512;限制管道缓冲区的大小为 512 Kbytes |
-s | 线程栈大小,以 Kbytes 为单位 | ulimit – s 512;限制线程栈的大小为 512 Kbytes |
-t | 最大的 CPU 占用时间,以秒为单位 | ulimit – t unlimited;对最大的 CPU 占用时间不进行限制 |
-u | 用户最大可用的进程数 | ulimit – u 64;限制用户最多可使用 64 个进程 |
-v | 进程最大可用的虚拟内存,以 Kbytes 为单位 | ulimit – v 200000;限制最大可用的虚拟内存为 200000 Kbytes |
咱们可使用ulimit -a查看咱们系统的全部限制编程
固然咱们都知道linux大部分的命令设置都是临时生效,并且ulimit命令只对当前终端生效小程序
若是须要永久生效的话,咱们有两种方法,windows
一种是将命令写至profile和bashrc中,至关于在登录时自动动态修改限制缓存
还有一种就是在/etc/security/limits.conf中添加记录(需重启生效,而且在/etc/pam.d/中的seesion有使用到limit模块)。安全
在/etc/security/limits.conf修改限制的格式以下bash
domino type item value
参数 | 描述 |
---|---|
domino | 是以符号@开头的用户名或组名,*表示全部用户 |
type | 设置为hard or soft |
item | 指定想限制的资源。如cpu,core nproc or maxlogins |
value | 是相应的 |
每一个进程的局部段描述表LDT都做为一个独立的段而存在,在全局段描述表GDT中要有一个表项指向这个段的起始地址,并说明该段的长度以及其余一些 参数。除上以外,每一个进程还有一个TSS结构(任务状态段)也是同样。因此,每一个进程都要在全局段描述表GDT中占据两个表项。
段寄存器中用做GDT表下标的位段宽度是13位,因此GDT中能够有213=8192个描述项。
除一些系统的开销(例如GDT中的第2项和第3项分别用于内核 的代码段和数据段,第4项和第5项永远用于当前进程的代码段和数据段,第1项永远是0,等等)之外,尚有8180个表项可供使用,因此理论上系统中最大的 进程数量是8180/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 65535
设置完之后,虽然咱们设置户建立进程数的硬限制和软限制都是65535,可是咱们还不能使用建立65535个进程
咱们在Linux还须要设置内核参数kernel.pid_max,这个参数我默认安装都是32768,
因此即便使用root账户,却不设置这个内核参数,整个系统最多能够建立的进程数就是32768,因此咱们须要进行以下设置:
sysctl -w kernel.pid_max=65535
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
而32位系统中,能够穿件381个线程,这个值和理论彻底相符,由于 32 位 linux 下的进程用户空间是 3G 的大小,也就是 3072M,用3072M/8M=384,可是实际上代码段和数据段等还要占用一些空间,这个值应该向下取整到 383,再减去主线程,获得 382。
那为何 linuxthreads 上还要少一个线程呢?这可太对了,由于 linuxthreads 还须要一个管理线程
为了突破内存的限制,能够有两种方法
用ulimit -s 1024
减少默认的栈大小
调用pthread_create
的时候用pthread_attr_getstacksize
设置一个较小的栈大小
要注意的是,即便这样的也没法突破1024 个线程的硬限制,除非从新编译 C 库
/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
fs.file-max = 1000000
内核支持的最大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文件描述符。
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 409600
设置nofile的hard limit还有一点要注意的就是hard limit不能大于/proc/sys/fs/nr_open,假如hard limit大于nr_open,注销后没法正常登陆。
能够修改nr_open的值:
echo 2000000 > /proc/sys/fs/nr_open
针对用户打开最大文件数的限制, 在limits.conf对应的nofile,无论是man手册仍是文件中说明都只是一句话
“maximum number of open files”,
它其实对应是单个进程能打开的最大文件数,一般为了省事,咱们想取消它的限制
根据man手册中,“values -1, unlimited or infinity indicating no limit”,-一、unlimited、infinity都是代表不作限制
但是当你实际给nofile设置成这个值,等你重启就会发现没法登陆系统了。
因而可知,nofile是有一个上限的,同时用ulimit测试:
ulimit -n unlimited
bash: ulimit: open files: cannot modify limit: 不容许的操做
写一个简单的for循环得出:
for V in `seq 100000 10000000`;do ulimit -n $V;[[ $? != 0 ]]&&break;done
再执行ulimit -n ,能够看到1048576就是nofile的最大值了,但为何是这个值?
1024∗1024=1048576,固然这并无什么卵用。
再跟踪一下咱们就会发现这个值实际上是由内核参数nr_open定义的:
cat /proc/sys/fs/nr_open
到此咱们就要提及nr_open,与file-max了,网上在说到设置最大文件数时偶尔有些帖子也说到要修改file-max,字面上看file-max确实像是对应最大文件数,而在linux内核文档中它们两的解释是:
执行:grep -r MemTotal /proc/meminfo | awk ‘{printf(“%d”,$2/10)}’,能够看到与file-max是相近的;
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内核的典型系统上(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位的
单位里某BSD FANS用AMD64笔记本跑小程序测试线程建立速度(线程建立后当即phread_detach()而后紧跟着pthread_exit(),共计 100万个线程),一样源码OpenBSD居然比FreeBSD快了3倍,何时OpenBSD也变得疯狂起来了?
测试单进程建立线程上限C源码(test.c)
参考