首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

[linux][memory]进程的最大内存使用量的讨论

前言: 一个进程最大能使用多少虚拟内存,能控制的地方还是比想象的多一点。 尤其是IaaS上,一个qemu进程能使用多少虚拟内存,就是对应着虚拟机的物理内存的最大限制。 分析: 1,limit 在shell敲命令:ulimit -v或者ulimit -a 可以看到当前shell的resource limit:

这里需要说明一下,在shell中敲ulimit的时候,其实控制shell的ulimit,并不能改变其他任何进程的resource limit情况。查看已经启动的进程的limit情况,使用cat /proc/PID/limit命令查看。另外,limit是可以继承的,子进程可以继承父进程的limit配置。所以,在shell中敲了ulimit配置,再执行命令是可以改变的。当然,在代码中可以使用long ulimit(int cmd, long newlimit)函数。 root用户的进程可以绕开这个检查。 2,memory lock 进程的内存,可能通过lru算法被淘汰,匿名页会被swap。如果不希望关键内存被swap,可以使用mlock把内存lock住,这样子就可以kernel就不会swap了。 先来看一段代码linux-4.0.4/mm/mlock.c:

先lock住,然后在执行__mm_populate。正常情况下,如果mmap(没有使用MAP_POPULATE标记位)分配了一段内存,没有访问之前,其实是没有分配物理page的。但是执行了mlock之后,会直接分配出来对应数量的page。写一个简单的小例子,会看到在执行mlock之后,top看到进程的RES会暴涨。 当然,mlock也是有resource limit限制的。ulimit -l是lock memory的限制。 在使用mlock的时候,会向kernel要很多page,如果内存紧张,那么kernel会回收内存,这个函数可能会被block住一段时间,如果实在要的page太多,最差情况可能会OOM,当然,不见得kernel就会杀掉当前进程。 3,MAP_POPULATE mmap函数flags可选参数。如果带着这个标志位,那么同样也是执行__mm_populate。这里需要注意的是kernel版本支持,在man page中写的比较具体。Populate (prefault) page tables for a mapping. For a file mapping, this causes read-ahead on the file. This will help to reduce blocking on page faults later. MAP_POPULATE is supported for private mappings only since Linux 2.6.23. 4,MAP_NORESERVE 设想一种情况:当前的主机上物理内存只有8G,按照swap比例100%计算,大约还有8G的swap空间,分配128G的虚拟内存,其实是分配不到那么多的物理内存与之映射的。大部分情况下,这个的请求都会失败。逻辑控制在linux-4.0.4/mm/mmap.c:

在分配虚拟内存的时候,会检查MAP_NORESERVE。如果不带这个标记位,就会根据物理内存大小、swap空间等参数 做进一步检查。如果带有这个标记位,则可以绕开这里的检查。 5,overcommit_memory 控制虚拟内存是否无条件超过物理内存大小。 查看:cat /proc/sys/vm/overcommit_memory 修改:echo 1 > /proc/sys/vm/overcommit_memory

参数说明,如果是1的话,则可以绕开检查;2的话,不允许;0的话,智能一点,计算复杂一些。 6,TASK_SIZE vma的最大范围,不能超过TASK_SIZE。TASK_SIZE是一个宏定义,和32bit/64bit相关,还和架构相关。在x86上,在32位机上是3G,在64位机上是((1UL << 47) – PAGE_SIZE)。 7,MAP_FIXED mmap函数的这个标记位还是慎重使用。不小心会segmentation fault。不小心会踩坏了其他的file mapping(如果刚好了映射了glibc),就会signal 11了。 后记: 这个问题还没完。。还没完。。 内存管理的问题,不会完。。

下一篇
举报
领券