core file size
core file size是限制core文件的大小,默认情况下是0,就是没有打开的,ulimit -c参数代表core file size,单位是blocks,一个blocks是1024个字节
core文件是什么呢?core文件其实就是内存的映像,当程序奔溃时,存储内存的相应信息,主要用于对程序进行调试,当程序奔溃时便会产生core文件,或者叫core dump文件,默认生成位置与可执行程序位于同一目录下
随便写个简单的c文件编译下
编译,执行会报错,正常会生成core dump文件,但是由于默认ulimit的core file size为0,未开启,所以目录下没有生成该文件
通过ulimit -c修改对core文件的大小限制
接着,重新执行下test
可以看到,生成core dump文件
当然如果生成的dump文件超过ulimit -c的限制大小的话,会被裁剪,最终生成一个不完整的core文件,core文件需要gdb -c指定文件查看
data seg size
data seg size是限制进程使用数据段的大小,一般来说这个限制会影响程序调用brk(系统调用)和sbrk(库函数)调用malloc时,如果发现vm不够了,就会用brk去内核申请
默认情况下data seg size是无限制的,所以我们设置个小的值,进行测试
设置限制可以使用最大为1kb的数据段,我们用一个程序对该限制进行测试
编译后执行
scheduling priority
scheduling priority是限制进程优先级的,就是进程的NICE值,这个值只对普通用户起作用,对root用户不起作用
scheduling priority默认值为0,nice值的范围为-20到20,优先级从高到底,-20最高
查看进程nice可以通过top查看ni列,或者通过ps -l 查看ni值
我们设置硬限制niec为-15-20之间,设置软限制nice值为-10-20之间
接着用nice命令,使命令执行的nice值为-10,在scheduling priority限制范围内
可以正常执行,接着,设置nice值为-11,超过软限制的值,再尝试下
我们切换到普通用户
可以看到,普通用户设置超过软限制的nice值的时候,提示不允许
file size
file size是限制进程产生的文件大小,默认情况不限制,我们设置个较小的值看下限制后的效果
file size的单位是blocks,上面说了一个blocks是1024字节,也就是1KB,我们设置100,然后创建文件看下
可以看到,file size生效,无法创建大于100KB的文件
pending signals
pending signals是限制信号的,linux下信号有64种,可以通过kill -l查看
编号为1-31的信号为传统unix支持的信号,是不可靠信号(非实时的),编号为32-64的信号是后来扩充的,称作可靠信号(实时信号),有兴趣的可以了解下linux信号机制
这个pending signals主要是表示可以被挂起/阻塞的最大信号数量,我们拿一段简单的代码,编译测试下
编译并执行,看结果
ulimit默认也是不限制,但是受限于系统,也就是上篇文章中的thread_max的值,我们讲pending signals值改为2,这里重新执行test,将只能保证挂起两个信号
max locked memory
max locked memory是限制内存锁定,这个参数同样也是只对普通用户起作用,对root用户不起作用,linux对内存是分页管理的,内存中的数据,当不再需要时,会被从物理内存交换到swap或磁盘上,有需要时会被交换到物理内存,因为内存的换入/换出有一定的性能损耗,所以有时候会需要将数据锁定到物理内存,比如数据库等,或安全角度考虑的,比如用户名、密码等,被交换到swap或磁盘会有泄密的可能,所以一直锁定再内存中
锁定内存的动作由mlock()函数来完成,mlock原型如下:
int mloc(const void *addr, size_t len);
写一段测试代码如下:
编译上面的测试代码,测试代码中,锁定2KB的数据到物理内存中
默认max locked memory是64KB,所以调整下该参数,设置比2KB小,执行该代码测试
root用户无效,切换到普通用户测试
普通用户测试,无法执行该脚本,增大max locked memory,重新测试
这里有个问题,我们代码里面锁定内存是2KB,但是实际输出锁定内存大小确实8KB,这是因为linux分配内存到页(page),每次只能锁定整页内存,所以我们在代码中添加getpagesize(),查看系统的分页大小
这里可以看到系统分页为4KB,然后除了分配的内存,还有动态连接库大小,所以分配出来的内存,要大于代码中指定的大小
open files
open files是限制进程打开文件的,这个值是针对所有用户的,表示可以在进程中打开文件的数量,默认是1024,这个值是我们服务器必须要调整的一个值,作为线上服务器,open files为1024是完全不够用的,经常会遇到Too many open files的问题,当然,有时候也需要检查程序问题,是否正常释放资源
通常是单进程使用文件句柄超过ulimit -n的值,我们可以通过lsof查看进程打开的句柄数量,命令如下:
第一列为句柄数量,第二列为进程pid
我们同样做个小实验,设置个小点的open files
所以,遇到Too man open files,如果不是程序问题,就需要考虑改大open files
POSIX message queues
POSIX message queues是限制可以创建使用POSIX消息队列的大小的,单位是bytes,默认是800KB
POSIX消息队列是linux ipc中很常用的一种通信方式,它通常用来在不同进程间发送特定格式的消息数据
同样用一段程序,对POSIX消息队列限制进行测试,代码如下
编译该程序,并限制POSIX消息队列最大值为1000字节,然后我们执行程序,看下效果
通过strace跟踪查看报错Too many open files
这里消息已经1280字节了,超过了POSIX消息队列的限制,我们修改POSIX消息队列大小,超过1280,再执行脚本试下
可以正常执行
real-time priority
real-time priority是限制程序实时优先级的范围,只针对普通用户
写小段代码测试下,程序实时优先级范围
编译后,切换到普通用户,默认real-time priority为0的情况测试如下
chrt命令用于调整进程的调度策略和优先级,和nice不同,nice是影响优先级的调整因子,也就是进程的优先级会根据nice来进行调整,但chrt是直接调整进程优先级的
接着调整real-time priority为20,再进行测试
使进程优先级为50再测试
如果你使用小于ulimit -r限制的优先级,仍提示不允许调整的话,需要修改内核参数,kernel.sched_rt_runtime_us为-1,允许调整
cpu time
cpu time是限制程序占用cpu的时间的,单位是秒,默认是没有限制的,我们仍然写段小的代码,测试下
还是编译,运行
查看进程,可以看到,一直占用CPU
接着改下cpu time限制为2秒,再运行程序
2秒后,程序被kill掉了
max user processes
max user processes是限制每个用户可以fork的进程数的,这里默认是不限的,而且该参数只对普通用户有效,我们还是写一小段代码测试下
编译后执行,这个代码就是
这里总共输出14个进程,除父进程外,其他13个进程都是test程序fork的,接着我们将max user processes设置小一点,再执行一次
没有效果,切换到普通用户,再测试
可以看到,创建到第二个子进程的时候,就停止了
max user processes会影响并发,比如nginx、php-fpm的fork子进程,或者mysql的最大连接数,这个参数,默认情况下是根据系统的thread-max来定的,参见上篇文章搞懂ulimit资源限制
virtual memory
virtual memory是限制进程使用虚拟内存大小,单位是KB,默认是不限制的,我们将它限制调整为8192KB,测试
测试ls命令执行,提示调用libc.so内存不足,用strace跟踪ls执行过程
可以看到mmap映射内存时,内存不够
以上就是ulimit的所有参数的详解,如有问题,欢迎留言交流