当前位置:嗨网首页>书籍在线阅读

34-超量使用和内存溢出(OOM)

  
选择背景色: 黄橙 洋红 淡粉 水蓝 草绿 白色 选择字体: 宋体 黑体 微软雅黑 楷体 选择字体大小: 恢复默认

超量使用和内存溢出(OOM)

和在应用请求页面就分配物理存储相比,在使用时刻才分配物理存储的过量使用机制允许系统运行更多、更大的应用程序。如果没有超量使用,用写时复制映射2GB文件需要内核划出2GB的物理存储。采用超量使用,映射2GB文件需要的存储量仅仅是进程映射区域中真正进行写操作的所有页面的大小。同样,没有超量使用,就算大多数页面都不需要进行写时拷贝,每个fork()操作都需要申请空闲内存来复制整个地址空间。

但是,如果系统中的进程为满足超量使用而申请的内存大于物理内存和交换空间之和,这时会怎样呢?在这种情况下,一个或者更多的分配一定会失败。因为内核已经承诺给进程分配内存了(系统调用成功返回),而这个进程尝试使用已分配的内存,内核只能杀死另一个进程并释放它的内存,以此来满足下一次分配需求。

当超量使用导致内存不足以满足一个请求时,我们就说发生了“内存溢出(out of memory,OOM)”。为了处理OOM问题,内核使用OOM终结者(killer)来挑选一个进程,并终止它。基于这个目的,内核会尝试选出一个最不重要且又占用很多内存的进程。

OOM 其实很少出现——所以采用超量使用效果很好,非常有实际意义。但是,可以肯定的是,没人希望发生OOM,而且进程突然被OOM 终结者(killer)终结了也往往是无法接受。

如果不希望系统出现这种情况,内核允许通过文件/proc/sys/vm/overcommit_memory禁止使用“超量使用”,和此功能相似的还有sysctl的vm.overcommit_memory参数。

vm.overcommit_memory参数的默认值是0,告诉内核执行适度的超量使用策略,在合理范围内实施超量使用,超出限定值时则不可使用。值为1时,确认所有的分配请求,将一切顾虑抛诸脑后。一些对存储要求较高的应用程序(例如在科学计算领域)倾向于请求比它们实际需要更多的内存,这时这个参数值就很有帮助。

当值为2时,会禁止使用所有的“超量使用”,启用“严格审计策略(strict accounting)”。在严格审计模式中,承诺的内存大小被严格限制在交换空间大小加上可调比例的物理内存大小。这个比例可以在文件/proc/sys/vm/overcommit_ratio里面设置,作用和vm.overcommit_ratio的sysctl参数相似。默认是50,限制承诺的内存总量是交换空间加上物理内存的一半。因为物理内存还必须包含着内核、页表、系统保留页、锁定页等等,实际上只有一部分可以被交换和满足承诺请求。

使用严格审计策略时要非常小心!许多系统设计者,被OOM终结者(killer)搞得崩溃了,认为严格审计才是解决之道。然而,应用程序常常执行一些不必要的请求操作,导致会严重使用“超量使用”,而允许这种行为也是设计虚拟内存的主要动机之一。

[1] 一些系统支持一系列的页面大小,由于这个原因,页面大小不是ABI(应用程序二进制接口)的一部分。应用程序必须在运行时获取页面大小,我们在第4章讨论过这个问题,本章我们将会加以回顾。

[2] 注:回想第5章fork()就是使用了写时拷贝来使子进程共享父进程的地址空间。

[3] 注:如此命名有一定的历史原因,是从block started by symbol得到的。

[4] 注:没有声明的函数返回值默认是int类型的。int到指针的强制类型转换并不是自动的,所以会产生警告。而强制类型转换会遮盖这个警告。