zram 的说明
zram 是 Linux 内核的一个模块,之前被称为“compcache”。 zram 通过在 RAM 内的压缩块设备
上分页,直到必须使用硬盘上的交换空间,以避免在磁盘上进行分页,从而提高性能。
zram 的开起和使用
一. Linux 内核的配置:
Symbol: ZRAM [=y]
│ Location:
│ -> DeviceDrivers
│ -> Stagingdrivers (
│ -> Memoryallocator for compressed pages (ZSMALLOC [=y])
Improved memory management
1.Validated memory-saving kernelconfigurations: Kernel Same-page Merging (KSM), and Swap to ZRAM.
Kill cached processes if about to beuncached and too large.
2.Don't allow large services to putthemselves back into A Services (so they can't cause the launcher to bekilled).
3.Kill processes (even ordinarilyunkillable ones such as the current IME) that get too large in idlemaintenance.
4.Serialize the launch of backgroundservices.
5.Tuned memory use of low-RAM devices:tighter out-of-memory (OOM) adjustment levels, smaller graphics caches,
etc.
第 6 页 共 15 页
图 1: ZRAM 的内核选择
二.Android 配置:
T3 Android 系统对 zram 已做了配置,更改有两个地方:
1.fstab.sun8iw11p1 文件中需要将配置打开:
zramsize=134217728 定义 zram 的大小是 128M.分配部分内存作 zram,大小建议为总内存的
10%-25%.
2.文件 android/system/core/init/init.c:
1136 //SWAP TO ZRAM if low mem devices
1137 if (!(get_dram_size() > 512)) {
1138 char trigger[] = {"early-fs"};
1139 ERROR("***************************LOW MEM DEVICE
DETECT");
1140 add_command(trigger, 2, args_swapon);
1141 char trigger2[] = {"post-fs-data"};
1142 add_command(trigger2, 3, args_write);
1143 }
第 7 页 共 15 页
从上面可以看到,当使用低内存(512M)时系统才会打开 zram,如果需要强制打开zram 可以将
此判断去除。
三.查看 zram 是否生效:
通过 cat /proc/meminfo 查看 swap 的大小,生效后 swap 的大小不为 0,如下:
第 8 页 共 15 页
Lowmemkill 的使用
lowmemkill 的说明
Android 是一个多任务系统, 也就是说可以同时运行多个程序, 这个大家应该很熟悉。 一般来说,
启动运行一个程序是有一定的时间开销的,因此为了加快运行速度,当你退出一个程序时, Android
并不会立即杀掉它,这样下次再运行该程序时,可以很快的启动。随着系统中保留的程序越来越多,
内存肯定会出现不足, low memory killer 就是在系统内存低于某值时,清除相关的程序,保障系统
保持拥有一定数量的空闲内存。
由于 Android 的 low memory kill 机制的产生,在内存低时将会对后台进程进行销毁,为此有可
能将一些关键性及产品重点应用进行销毁,如行车记录功能,当系统符合达到一定的门限时将会关
闭此功能,严重的影响了用户体验和产品的性能。
lowmemkill 的门限制定
1.LMK 的门限可以通过以下方式查看,(在低内存时需要配置 ro.config.low_mem = true)
cat /sys/module/lowmemorykiller /parameters/minfree
单位为 4KB.
2.LMK 进程调整级别查看:
cat /sys/module/lowmemorykiller /parameters/adj
限制 LMK 不销毁的指定应用
针对 ANROID 的 LMK 会将后台重要进程销毁机制,我们做了屏蔽处理。
1.添加白名单列表,定义如下(注:名单字符不能超过 15 个字节):
static char *aw_whiteName[12] =
{
"launcher",
"mediaserver",
"dvr",
"goc",
"gps",
};
第 9 页 共 15 页
2.添加处理名单列表代码:
ION 预留内存
ION 的定义
ION 是 Google 的内存管理器,用来支持不同的内存分配机制,如 CARVOUT,物理连续内存
@@ -114,7 +126,28 @@ static int lowmem_shrink(struct shrinker *s, struct
shrink_control *sc)
if (tsk->flags & PF_KTHREAD)
continue;
-
+//golden modify here
+if(tsk)
+{
+int n = 0;
+int notkill = 0;
+int len = sizeof(aw_whiteName)/sizeof(aw_whiteName[0]);
+for(n = 0 ;n < len ;n++)
+{
+if(aw_whiteName[n] == NULL)
+break;
+//printk(KERN_ERR "len = %d,n = %d,str =%s\n",len,n,aw_whiteName[n]);
+if(strstr(tsk->comm,aw_whiteName[n]))
+{
+// printk(KERN_ERR "match process is %s ,not killit!\n",tsk->comm);
+notkill = 1;
+break;
+}
+}
+if(notkill)
+continue;
+}
+//golden moidfy end
p = find_lock_task_mm(tsk);
if (!p)
continue;
第 10 页 共 15 页
(kmalloc), 虚拟地址连续但物理不连续内存(vmalloc), IOMMU 等。
用户空间和内核空间都可以使用 ION,用户空间是通过/dev/ion 来创建 client 的。
Heap: 用来表示内存分配的相关信息,包括 id, type, name 等。用 struct ion_heap 表示。
Client: Ion 的使用者,用户空间和内核控件要使用 ION 的 buffer,必须先创建一个 client,一个 client
可以有多个 buffer,用 struct ion_buffer 表示。
Handle: 将 buffer 该抽象出来,可以认为 ION 用 handle 来管理 buffer,一般用户直接拿到的是 handle,
而不是 buffer。 用 struct ion_handle 表示。
heap 类型: 由于 ION 可以使用多种 memory 分配机制,例如物理连续和不连续的,所以ION 使用
enum ion_heap_type 表示
ION 的申请类型定义如下:
. ION 的预留原则
ION 的预留定义通过 DTS 进行配置
文件: linux-3.10/arch/arm/boot/dts/sun8iw11p1.dtsi 配置定义如下
25 /**
26 * enum ion_heap_types - list of allpossible types of heaps
27 * @ION_HEAP_TYPE_SYSTEM: memoryallocated via vmalloc
28 * @ION_HEAP_TYPE_SYSTEM_CONTIG: memoryallocated via kmalloc
29 |
* @ION_HEAP_TYPE_CARVEOUT: |
memory allocated from a prereserved |
30 |
* |
carveout heap, allocations are physically |
31 |
* |
contiguous |
32 |
* @ION_HEAP_TYPE_DMA: |
memory allocated via DMAAPI |
33 |
* @ION_NUM_HEAPS: |
helper for iterating over heaps, a bit mask |
34 |
* |
is used to identify the heaps, so only 32 |
35 |
* |
total heap types are supported |
36 |
*/ |
37 enum ion_heap_type {
38 ION_HEAP_TYPE_SYSTEM,
39 ION_HEAP_TYPE_SYSTEM_CONTIG,
40 ION_HEAP_TYPE_CARVEOUT,
41 ION_HEAP_TYPE_CHUNK,
42 ION_HEAP_TYPE_DMA,
43 ION_HEAP_TYPE_SECURE = 6, /* to matchthe value in linux-3.4 */
44 ION_HEAP_TYPE_CUSTOM, /* must be lastso device specific heaps always
45 are at the end of this enum */
46 |
ION_NUM_HEAPS = 16, |
47 }; |
第 11 页 共 15 页
/memreserve/ 0x50600000 0xFA00000; /* ion carvout heap revserve :
[0x58000000~0x68000000], size = 256M */
预留原则:保证高端内存,尽量从低端内存来分配。内存分配管理如下图:
116 ion {
117 compatible = "allwinner,sunxi-ion";
118 /*types is list here:
119 ION_HEAP_TYPE_SYSTEM = 0,
120
ION_HEAP_TYPE_SYSTEM_CONTIG = 1,
121 ION_HEAP_TYPE_CARVEOUT = 2,
122 ION_HEAP_TYPE_CHUNK = 3,
123 ION_HEAP_TYPE_DMA = 4
124 **/
125 system_contig{
126 type = <1>;
127 name = "system_contig";
128 };
129 carvout{
130 type = <2>;
131 name = "carvout";
132 base = <0x50600000>;
133 size = <0xFA00000>;
134 };
135 system{
136 type = <0>;
137 name = "system";
138 };
139 };
第 12 页 共 15 页
高端和低端内存的大小受 VM 大小决定,Android 应用的访问优先分配高端内存。
在 VMA 配置在 384M 时,低端的内存有 634M,ION 的分配原则是从低端进行分配
低端的起始地此是:0x40000000,结束地此是:0x67A00000,报证预留的范围在此范围内
第 13 页 共 15 页
Cache 清理机制
1.启动 cache 清理服务
使用 init.sun8iw11p1.rc 启动 cache 清理服务。
service drop_caches /sbin/busybox sh /system/bin/flushcache.sh
user root
group root system
disabled
oneshot
2.Cache 清理启动门限
android/frameworks/base/services/java/com/android/server/am/ActivityManagerService.java
在文件中定义:
static final int SW_MEM_FLUSH_THRESTHOD1 = 120000;// =< 512M 25%
static final int SW_MEM_FLUSH_THRESTHOD2 = 300000;// > 512M 38%
这个门限可以根据实际使用进行修改。代码实现如下:
1096 |
private void flushPageCache() { |
1097 |
MemInfoReader memInfo = new MemInfoReader(); |
1098 |
memInfo.readMemInfo(); |
1099 |
if( (memInfo.getTotalSizeKb() <= 524288 && |
memInfo.getCachedSizeKb() > SW_MEM_FLUSH_THRESTHOD1) ||
1100 |
(memInfo.getTotalSizeKb() > 524288 && |
memInfo.getCachedSizeKb() > SW_MEM_FLUSH_THRESTHOD2) ) { |
1101 |
SystemProperties.set("ctl.start", "drop_caches"); |
|
1102 |
} |
|
1103 |
Message msg = Message.obtain(); |
|
1105 |
msg.what |
= SW_FLUSH_PAGECACHE_MSG; |
1106 |
mHandler.sendMessageDelayed(msg, |
SW_SEND_MSG_DELAYED);
1107 return;
1108 }