写点什么

实例详解 Linux 下 ulimit 每个参数

发布于: 2021 年 02 月 21 日

接着上篇文章继续 ulimit,上篇也说了,这篇主要是通过实例,或者实验,对 ulimit -a 的每个参数具体作用,及会有什么影响做一个整理,废话不多说,直接开始!



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 的所有参数的详解,如有问题,欢迎留言交流


发布于: 2021 年 02 月 21 日阅读数: 570
用户头像

有一点想法的电脑维修工 2020.07.14 加入

一位有些想法的技术爱好者

评论

发布
暂无评论
实例详解Linux下ulimit每个参数