1、问题现象和分析:
测试时发现当系统中空闲内存还有很多时,就报内存分配失败了,所有进程都报内存分配失败:
sshd@localhost:/var/log>free
             total       used       free     shared    buffers     cached
Mem:      12183700    8627972    3555728          0     289252     584444
-/+ buffers/cache:    7754276    4429424
Swap:            0          0          0
sshd@localhost:/var/log>free
-bash: fork: Cannot allocate memory
sshd@localhost:/var/log>cat /proc/meminfo
-bash: fork: Cannot allocate memory

而messages日志中,也没有OOM相关的记录。最后确认原因为:/proc/sys/vm/overcommit_memory参数导致。
该环境中该参数设置为2,表示“No overcommit”,即系统中所有进程占用的虚拟内存空间不能超过上限:
cat /proc/meminfo
CommitLimit:    12061860 kB  //虚拟地址空间的上限
Committed_AS:    8625360 kB  //当前的使用量

而该参数应该默认是0,这种情况下,只有还有空闲的物理内存,就可以继续分配,不受虚拟地址空间的限制。
echo 0 > /proc/sys/vm/overcommit_memory
如此修正后解决。

2、关于overcommit_memory说明:

取值为0,系统在为应用进程分配虚拟地址空间时,会判断当前申请的虚拟地址空间大小是否超过剩余内存大小,如果超过,则虚拟地址空间分配失败。因此,也就是如果进程本身占用的虚拟地址空间比较大或者剩余内存比较小时,fork、malloc等调用可能会失败。

取值为1,系统在为应用进程分配虚拟地址空间时,完全不进行限制,这种情况下,避免了fork可能产生的失败,但由于malloc是先分配虚拟地址空间,而后通过异常陷入内核分配真正的物理内存,在内存不足的情况下,这相当于完全屏蔽了应用进程对系统内存状态的感知,即malloc总是能成功,一旦内存不足,会引起系统OOM杀进程,应用程序对于这种后果是无法预测的

取值为2,则是根据系统内存状态确定了虚拟地址空间的上限,由于很多情况下,进程的虚拟地址空间占用远大小其实际占用的物理内存,这样一旦内存使用量上去以后,对于一些动态产生的进程(需要复制父进程地址空间)则很容易创建失败,如果业务过程没有过多的这种动态申请内存或者创建子进程,则影响不大,否则会产生比较大的影响

3、相应代码分析:

点击(此处)折叠或打开

  1. int __vm_enough_memory(struct mm_struct *mm, long pages, int cap_sys_admin)
  2. {
  3. unsigned long free, allowed;
  4. vm_acct_memory(pages);
  5. /*
  6. * Sometimes we want to use more memory than we have
  7. */
  8. if (sysctl_overcommit_memory == OVERCOMMIT_ALWAYS) //overcommit_memory=1,直接返回成功,不做任何限制。
  9. return 0;
  10. if (sysctl_overcommit_memory == OVERCOMMIT_GUESS) { //overcommit_memory=0,启发式方式,根据当前系统中空闲内存状况来决定是否可以分配内存。
  11. unsigned long n;
  12. free = global_page_state(NR_FILE_PAGES);
  13. free += nr_swap_pages;
  14. /*
  15. * Any slabs which are created with the
  16. * SLAB_RECLAIM_ACCOUNT flag claim to have contents
  17. * which are reclaimable, under pressure. The dentry
  18. * cache and most inode caches should fall into this
  19. */
  20. free += global_page_state(NR_SLAB_RECLAIMABLE);
  21. /*
  22. * Leave the last 3% for root
  23. */
  24. if (!cap_sys_admin)
  25. free -= free / 32; //root用户可以在free更少(3%)的时候,分配内存。
  26. if (free > pages) // pages为需要分配的内存大小,free为根据一定规则算出来的“空闲内存大小”,第一次free仅为NR_FILE_PAGES+NR_SLAB_RECLAIMABLE,由于直接或者系统中“实际空闲”内存代价比较大,所以进行分阶判断,提高效率。
  27. return 0;
  28. /*
  29. * nr_free_pages() is very expensive on large systems,
  30. * only call if we're about to fail.
  31. */
  32. n = nr_free_pages(); //当第一次判断不满足内存分配条件时,再进行“实际空闲”内存的获取操作。
  33. /*
  34. * Leave reserved pages. The pages are not for anonymous pages.
  35. */
  36. if (n
  37. goto error;
  38. else
  39. n -= totalreserve_pages;
  40. /*
  41. * Leave the last 3% for root
  42. */
  43. if (!cap_sys_admin)
  44. n -= n / 32;
  45. free += n;
  46. if (free > pages)
  47. return 0;
  48. goto error;
  49. }
  50. allowed = (totalram_pages - hugetlb_total_pages()) //当overcommit_memory=2时,根据系统中虚拟地址空间的总量来进行限制。
  51. * sysctl_overcommit_ratio / 100;
  52. /*
  53. * Leave the last 3% for root
  54. */
  55. if (!cap_sys_admin)
  56. allowed -= allowed / 32;
  57. allowed += total_swap_pages;
  58. /* Don't let a single process grow too big:
  59. leave 3% of the size of this process for other processes */
  60. if (mm)
  61. allowed -= mm->total_vm / 32;
  62. if (percpu_counter_read_positive(&vm_committed_as) allowed)
  63. return 0;
  64. error:
  65. vm_unacct_memory(pages);
  66. return -ENOMEM;
  67. }

又一次内存分配失败(关于overcommit_memory)相关推荐

  1. 内存分配失败错误处理

    一.C语言中的malloc/calloc/realloc/valloc/alloca/memalign函数: 这样的内存分配函数在内存分配失败时都返回空指针,因此,在调用返回时,检查返回值的方法比较简 ...

  2. kmalloc使用不当导致内存分配失败问题

    1.介绍 本文记录分析驱动模块kmalloc接口的flags参数使用不当,导致分配内存失败的问题,主要记录了分析过程和给出的解决方法. 1.1背景介绍 在对spi nand flash进行读写老化,因 ...

  3. keilcjson内存分配失败_iOS标准库中常用数据结构和算法之内存池

    黑客技术点击右侧关注,了解黑客的世界! Java开发进阶点击右侧关注,掌握进阶之路! Linux编程点击右侧关注,免费入门到精通! 作者丨欧阳大哥2013https://www.jianshu.com ...

  4. python内存分配失败_关于python:如何避免[Errno 12]无法分配使用子进程模块导致的内存错误...

    完整的工作测试案例 当然,根据您在本地和远程计算机上的内存,您的阵列大小会有所不同. z1 = numpy.random.rand(300000000,2); for i in range(1000) ...

  5. c语言链表内存分配失败,链表的C语言实现之动态内存分配

    链表的C语言实现之动态内存分配 來源:互聯網  2008-06-01 02:05:07  評論 一.为什么用动态内存分配 但我们未学习链表的时候,假如要存储数量比较多的同类型或同结构的数据的时候,总是 ...

  6. 计算机可用内存分配失败,你们都被忽悠了! 其实可用内存大才有用

    [PConline 杂谈]随着这几年安卓手机的硬件快速升级,手机的运行内存(本文后续页面将"运行内存"简称为内存或者RAM)也越来越大,从最初的512M到1GB,再到现在主流的2G ...

  7. 计算机可用内存分配失败,安装内存和实际可用内存不一样什么原因

    通常我们安装内存条时候都有显示具体内存,但是有时出现安装内存和实际可用内存不一致?为什么会不一样呢?下面我们一起来看看其中的原因和解决方法. 一.你安装的不是64位Win7系统 Win7 32位只能识 ...

  8. C语言malloc动态分配内存分配失败怎么办?exit(OVERFLOW);(include <cstdlib>)

    如:(见<大话数据结构>147页) QueuePtr s = (QueuePtr)malloc(sizeof(QNode)); if(!s){exit(OVERFLOW); } exit为 ...

  9. 【 C 】动态内存分配实用案例(二)之复制字符串

    用动态分配内存制作一个字符串的一份拷贝.注意:调用程序应该负责检查这块内存是否分配成功,这样做允许程序以任何它所希望的方式对错误作出反应. #nclude <stdlib.h> #incl ...

最新文章

  1. R语言构建xgboost模型使用早停法训练模型(early stopping):自定义损失函数(目标函数,loss function)、评估函数(evaluation function)
  2. shell中的特殊变量
  3. 官网快速搭建spring boot 项目
  4. 鲜为人知的DC-DC外围电感选型方法
  5. 潮美之夜见证“夜拍王”诞生,荣耀10 GT照亮三里屯
  6. cmd oracle sys登录_oracle忘记sys/system/scott用户密码的解决方法
  7. 图解从上电到执行main函数的处理
  8. 数字图像处理--图像二阶导数的本质
  9. ABViewer免费汉化下载注册地址图形查看器教程功能介绍
  10. html css拖拽设计,css绘制三角形 和 HTML拖拽事件
  11. request与在php安全,request导致的安全性问题分析
  12. Java指定屏幕区域截屏
  13. Ant Deign Pro - ProTable - 高级表格 通用打印组件
  14. 计算机开机响三短嘀嘀,电脑显示器不亮,开机2短3长报警音什么情况啊?:电脑...
  15. 初中计算机操作题五环,第五课 电脑出算术题 课件
  16. 区块链-压缩格式的密钥
  17. 如何判断两条直线是否相交
  18. [面试经验]一汽大众旗下车联网公司摩斯智联面试记
  19. Yii Framework 开发教程(31) Zii组件-DetailView 示例
  20. 《数论概论》读书笔记(第二章)勾股数组

热门文章

  1. VB.Net实现Web Service的基础
  2. day22-Model数据验证以及钩子
  3. windows 2003几个优化技巧
  4. [HNOI2008]遥远的行星
  5. XDU 翼讯账号算法
  6. virtualbox添加slic2.
  7. Git Gitlab 使用指南
  8. 第一行代码读书笔记1+常见错误分析
  9. mysql数据库引擎介绍
  10. 微软MCITP系列课程(二七)管理域和林信任