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

简介:
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
本文转自demoblog博客园博客,原文链接http://www.cnblogs.com/0616--ataozhijia/p/4038295.html如需转载请自行联系原作者

demoblog
相关文章
|
7月前
|
Linux 数据库 Perl
【YashanDB 知识库】如何避免 yasdb 进程被 Linux OOM Killer 杀掉
本文来自YashanDB官网,探讨Linux系统中OOM Killer对数据库服务器的影响及解决方法。当内存接近耗尽时,OOM Killer会杀死占用最多内存的进程,这可能导致数据库主进程被误杀。为避免此问题,可采取两种方法:一是在OS层面关闭OOM Killer,通过修改`/etc/sysctl.conf`文件并重启生效;二是豁免数据库进程,由数据库实例用户借助`sudo`权限调整`oom_score_adj`值。这些措施有助于保护数据库进程免受系统内存管理机制的影响。
|
8月前
|
存储 Linux
linux中的目录操作函数
本文详细介绍了Linux系统编程中常用的目录操作函数,包括创建目录、删除目录、读取目录内容、遍历目录树以及获取和修改目录属性。这些函数是进行文件系统操作的基础,通过示例代码展示了其具体用法。希望本文能帮助您更好地理解和应用这些目录操作函数,提高系统编程的效率和能力。
311 26
|
10月前
|
Linux
【Linux】System V信号量详解以及semget()、semctl()和semop()函数讲解
System V信号量的概念及其在Linux中的使用,包括 `semget()`、`semctl()`和 `semop()`函数的具体使用方法。通过实际代码示例,演示了如何创建、初始化和使用信号量进行进程间同步。掌握这些知识,可以有效解决多进程编程中的同步问题,提高程序的可靠性和稳定性。
452 19
|
10月前
|
Linux Android开发 开发者
linux m、mm、mmm函数和make的区别
通过理解和合理使用这些命令,可以更高效地进行项目构建和管理,特别是在复杂的 Android 开发环境中。
445 18
|
10月前
|
存储 监控 Linux
嵌入式Linux系统编程 — 5.3 times、clock函数获取进程时间
在嵌入式Linux系统编程中,`times`和 `clock`函数是获取进程时间的两个重要工具。`times`函数提供了更详细的进程和子进程时间信息,而 `clock`函数则提供了更简单的处理器时间获取方法。根据具体需求选择合适的函数,可以更有效地进行性能分析和资源管理。通过本文的介绍,希望能帮助您更好地理解和使用这两个函数,提高嵌入式系统编程的效率和效果。
414 13
|
12月前
|
Linux API 开发工具
FFmpeg开发笔记(五十九)Linux编译ijkplayer的Android平台so库
ijkplayer是由B站研发的移动端播放器,基于FFmpeg 3.4,支持Android和iOS。其源码托管于GitHub,截至2024年9月15日,获得了3.24万星标和0.81万分支,尽管已停止更新6年。本文档介绍了如何在Linux环境下编译ijkplayer的so库,以便在较新的开发环境中使用。首先需安装编译工具并调整/tmp分区大小,接着下载并安装Android SDK和NDK,最后下载ijkplayer源码并编译。详细步骤包括环境准备、工具安装及库编译等。更多FFmpeg开发知识可参考相关书籍。
375 0
FFmpeg开发笔记(五十九)Linux编译ijkplayer的Android平台so库
|
Linux Shell
Linux系统编程:掌握popen函数的使用
记得在使用完 `popen`打开的流后,总是使用 `pclose`来正确关闭它,并回收资源。这种做法符合良好的编程习惯,有助于保持程序的健壮性和稳定性。
539 6
|
Linux Shell
Linux系统编程:掌握popen函数的使用
记得在使用完 `popen`打开的流后,总是使用 `pclose`来正确关闭它,并回收资源。这种做法符合良好的编程习惯,有助于保持程序的健壮性和稳定性。
329 3
在Linux内核中根据函数指针输出函数名称
在Linux内核中根据函数指针输出函数名称
|
Linux PHP
Linux CentOS 宝塔 Suhosin禁用php5.6版本eval函数详细图文教程
【8月更文挑战第27天】本文介绍两种禁用PHP执行的方法:使用`PHP_diseval_extension`禁用和通过`suhosin`禁用。由于`suhosin`不支持PHP8,仅适用于PHP7及以下版本,若服务器安装了PHP5.6,则需对应安装`suhosin-0.9.38`版本。文章提供了详细的安装步骤,并强调了宝塔环境下与普通环境下的PHP路径差异。安装完成后,在`php.ini`中添加`suhosin.so`扩展并设置`executor.disable_eval = on`以禁用执行功能。最后通过测试代码验证是否成功禁用,并重启`php-fpm`服务生效。
328 2

热门文章

最新文章