[Android Memory] Linux下malloc函数和OOM Killer

时间:2022-09-26 14:25:15
http://www.linuxidc.com/Linux/2010-09/28364.htm
Linux下malloc函数主要用来在用户空间从heap申请内存,申请成功返回指向所分配内存的指针,申请失败返回NULL。默认情况下,Linux内核使用“乐观的”分配内存策略,首先粗略估计系统可使用的内存数,然后分配内存,但是在使用的时候才真正把这块分配的内存给你。这样一来,即使用malloc申请内存没有返回NULL,你也不一定能完全使用这块内存,特别是在一次或连续多次申请很多内存的时候。
 
如果一直连续用malloc申请内存,而不真正使用,所申请的内存总数可以超过真正可以使用的内存数。但是当真正使用这块内存,比如用memset或bzero函数一次性把所申请到的大块内存“使用掉”,Linux系统就会Out Of Memory,这个时候OOM Killer就会kill掉用户空间的其他进程来腾出更多可使用内存。
 
OOM Killer根据OOM score来决定kill哪个进程,OOM score可以看/proc/<PID>/oom_score,score由badness函数计算得出,根据进程运行时间长短,进程优先级,进程所使用的内存数等等。可以通过/proc/<PID>/oom_adj来干预计算socre,这个值的取值范围是-17~15,如果是-17该进程就永远不会被kill(这个可能也和内核版本有关,不见得所有内核版本都支持,得实际试试)。
 
“默认情况”Linux是这种做的,“默认情况”是指/proc/sys/vm/overcommit_memory为0的时候。这个参数也可以调整,如果为1表示“来着不拒”,只要你malloc过来申请,我啥都不做,立马给你分配内存,这样的话性能就会有大幅度的提高;如果为2表示Linux会精确计算所有可使用的内存和所申请的内存,如果所申请的超过的可使用的内存数就返回NULL。可使用的内存值计算方法,虚拟内存(swap)+ /proc/sys/vm/overcommit_memory(百分比) × 物理内存。/proc/sys/vm/overcommit_memory默认值为50,计算起来就是50%的物理内存数。
 
Linux自身内核会占一部分内存,还有buffer/cache所占用的内存,所以实际上能被malloc申请后使用的内存并非物理内存大小,demsg的输出里面包含了相关信息(如果看不到,可能是被别的信息冲掉了,重启系统,在系统起来后马上看):
Memory: 2071220k/2097152k available (2122k kernel code, 24584k reserved, 884k data, 228k init, 1179584k highmem)
 
关于OOM Killer的proc文件系统
 
http://book.2cto.com/201302/16321.html
 

下面开始介绍与OOM Killer相关的proc文件系统。
/proc/<PID>/oom_adj

为/proc/<PID>/oom_adj设置值就可以调整得分。调整值的范围为–16~15。正的值容易被OOM Killer选定。负值可能性较低。例如,当指定3时,得分就变为23倍;当指定–5时,得分就变为1/25。

“–17”是一个特殊的值。如果设置为–17,就会禁止OOM Killer发出的信号(从Linux 2.6.12开始支持设置–17)。

在OOM Killer运行的情况下,为了实现远程登录而想要将sshd排除在对象外时,可以执行下列命令。
# cat /proc/'cat /var/run/sshd.pid'/oom_score
15
# echo -17 >  /proc/'cat /var/run/sshd.pid'/oom_adj
# tail /proc/'cat /var/run/sshd.pid'/oom_*
==> /proc/2278/oom_adj <==
-17
==> /proc/2278/oom_score <==
0                               /*得分变成0*/

Linux 2.6.18开始可以使用/proc/<PID>/oom_adj。内容记载在Documentation /filesystems/proc.txt中。
/proc/sys/vm/panic_on_oom

将/proc/sys/vm/panic_on_oom设置为1时,在OOM Killer运行时可以不发送进程信号,而是使内核产生重大故障。
# echo 1 > /proc/sys/vm/panic_on_oom
/proc/sys/vm/oom_kill_allocating_task

从Linux 2.6.24开始proc文件系统就有oom_kill_allocating_task。如果对此设置除0以外的值,则促使OOM Killer运行的进程自身将接收信号。此处省略对所有进程的得分计算过程。
# echo 1 > /proc/sys/vm/oom_kill_allocating_task

这样就不需要参照所有进程,但是也不会考虑进程的优先级和root权限等,只发送信号。
/proc/sys/vm/oom_dump_tasks

从Linux 2.6.25开始,将oom_dump_tasks设置为除0以外的值时,在OOM Killer运行时的输出中会增加进程的列表信息。

下面为设置示例。
# echo 1 > /proc/sys/vm/oom_dump_tasks

列表信息显示如下,可以使用dmesg或syslog来确认。
[ pid ]   uid  tgid total_vm      rss cpu oom_adj name
[    1]     0     1     2580        1   0       0 init
[  500]     0   500     3231        0   1     -17 udevd
[ 2736]     0  2736     1470        1   0       0 syslogd
[ 2741]     0  2741      944        0   0       0 klogd
[ 2765]    81  2765     5307        0   0       0 dbus-daemon
[ 2861]     0  2861      944        0   0       0 acpid
...
[ 3320]     0  3320   525842   241215   1       0 stress
/proc/<PID>/oom_score_adj

从Linux 2.6.36开始都安装了/proc/<PID>/oom_score_adj,此后将替换为/proc/ <PID>/oom_adj。详细内容请参考Documentation/feature-removal-schedules.txt。即使当前是对/proc/<PID>/oom_adj进行的设置,在内核内部进行变换后的值也是针对/proc/<PID>/oom_score_adj设置的。

/proc/<PID>/oom_score_adj可以设置–1000~1000之间的值。设置为–1000时,该进程就被排除在OOM Killer强制终止的对象外。

在内核2.6.36以后的版本中写入oom_adj,只会输出一次如下的信息。
# dmesg
.....
udevd (60): /proc/60/oom_adj is deprecated, please use /proc/60/oom_score_adj instead.

[Android Memory] Linux下malloc函数和OOM Killer的更多相关文章

  1. linux下syscall函数,SYS&lowbar;gettid,SYS&lowbar;tgkill

    出处:http://blog.chinaunix.net/uid-28458801-id-4630215.html     linux下syscall函数,SYS_gettid,SYS_tgkill  ...

  2. 对于linux下system&lpar;&rpar;函数的深度理解&lpar;整理&rpar;

    原谅: http://blog.sina.com.cn/s/blog_8043547601017qk0.html 这几天调程序(嵌入式linux),发现程序有时就莫名其妙的死掉,每次都定位在程序中不同 ...

  3. Linux下c函数dlopen实现加载动态库so文件代码举例

    dlopen()是一个强大的库函数.该函数将打开一个新库,并把它装入内存.该函数主要用来加载库中的符号,这些符号在编译的时候是不知道的.这种机制使得在系统中添加或者删除一个模块时,都不需要重新编译了. ...

  4. 转:对于linux下system&lpar;&rpar;函数的深度理解&lpar;整理&rpar;

    这几天调程序(嵌入式linux),发现程序有时就莫名其妙的死掉,每次都定位在程序中不同的system()函数,直接在shell下输入system()函数中调用的命令也都一切正常.就没理这个bug,以为 ...

  5. 【C&sol;C&plus;&plus;】Linux下system&lpar;&rpar;函数引发的错误

    http://my.oschina.net/renhc/blog/54582 [C/C++]Linux下system()函数引发的错误 恋恋美食  恋恋美食 发布时间: 2012/04/21 11:3 ...

  6. &lbrack;转帖&rsqb;Linux下fork函数及pthread函数的总结

    Linux下fork函数及pthread函数的总结 https://blog.csdn.net/wangdd_199326/article/details/76180514 fork Linux多进程 ...

  7. &lpar;笔记&rpar;Linux下system&lpar;&rpar;函数的深度理解&lpar;整理&rpar;

    注:从其它地方转的非常好的一篇文章,值得深究! 这几天调程序(嵌入式linux),发现程序有时就莫名其妙的死掉,每次都定位在程序中不同的system()函数,直接在shell下输入system()函数 ...

  8. linux下sprintf&lowbar;s函数的替代

    error code: ]; sprintf_s(buf, , "predicted position:(%3d, %3d)", predict_pt.x, predict_pt. ...

  9. Linux下printf函数显示不同的颜色(转)

    Linux下printf函数显示不同的颜色 在学习Linux网络编程的时候做一个聊天系统,当时为了界面更漂亮点,于是搜索了下关于printf()函数的用法,给printf的输出加上些特效比如颜色,可以 ...

随机推荐

  1. MFC中ClistCtrl的&equals;NM&lowbar;CUSTOMDRAW消息

    =NM_CUSTOMDRAW是你点击列表内部是的消息映射: 例如:我想在我删除一行列表的数据,但是删除后下一行数据继续保持高亮状态 void CChildView::OnDel() { int cou ...

  2. SqlCommand执行带GO的SQL脚本文件

    今天工作中遇到了这个问题,其实只要把GO替换成“;”就行了,其它人写的例子用Split来拆分这一个脚本文件的内容,完全没有必要.希望对你有用.

  3. sqlserver 简单的创建数据库

    简简单单,作为不是牛逼的程序来说,这是很容易忘记的sql语句: use mastergo --判断是否存在该数据库if exists(select *from Sysdatabases where n ...

  4. 设置linux虚拟机的固定ip、防火墙的一些操作

    安装好虚拟机后,需要设置其固定ip,这样才可以连接该虚拟服务器 设置步骤如下 1.进入network-scripts目录 cd /etc/sysconfig/network-scripts 2.编辑n ...

  5. 关于JavaScript中的几种匿名行数的写法

     匿名函数没有实际名字,也没有指针,怎么执行滴? 其实大家可以看看小括号的意义就应该可以理解.小括号有返回值,也就是小括号内的函数或者表达式的返回值,所以说小括号内的function返回值等于小括 ...

  6. Redis高级特性介绍及实例分析

    转自:http://www.jianshu.com/p/af7043e6c8f9   Redis基础类型回顾 String Redis中最基本,也是最简单的数据类型.注意,VALUE既可以是简单的St ...

  7. BZOJ2142 礼物 扩展lucas 快速幂 数论

    原文链接http://www.cnblogs.com/zhouzhendong/p/8110015.html 题目传送门 - BZOJ2142 题意概括 小E购买了n件礼物,送给m个人,送给第i个人礼 ...

  8. h5中input的request属性提示文字字段

    <input type="password" class="form-control" name="passWord" require ...

  9. logger日志模块

    简单配合模式: import logging#简单配置logging.basicConfig(level=logging.DEBUG, format='%(asctime)s %(filename)s ...

  10. android 8&period;0 intent安装apk失败屏幕闪过

    需要做两处设置: 1.android8.0要加一条权限: <uses-permission android:name="android.permission.REQUEST_INSTA ...