一、概述
Linux系统当可用内存较低的时候oom killer机制会根据一定的规则去杀掉一些进程来释放内存,而Android系统的LowMemoryKiller机制就是以此功能为基础做了一些调整。Android系统中的APP在使用完成之后并不会马上被杀掉,而是驻留在内存中,当下一次在此进入此应用的时候可以省去进程创建的过程,加快启动速度。LowMemoryKiller机制会在内存资源紧张的时候,杀掉一些进程来回收内存。
二、整体架构
1.AMS部分的ProcessList
2.Native进程lmkd
3.内核中的LowMemoryKiller部分
Framework中的ProcessList和Native的lmkd进程通过Socket进行进程间通信,而lmkd和内核中的LowMemoryKiller通过writeFileString向文件节点写内容方法进行通信
Framework层通过一定的规则调整进程的adj的值和内存空间阀值,然后通过socket发送给lmkd进程
lmkd两种处理方式:
一种将阀值写入文件节点发送给内核的LowMemoryKiller,由内核进行杀进程处理
另一种是lmkd通过cgroup监控内存使用情况,自行计算杀掉进程。
三、lmkd的启动和初始化
lmkd是一个native进程,由init进程启动,定义在/system/core/lmkd/lmkd.rc中
service lmkd /system/bin/lmkd
class core
group root readproc
critical
socket lmkd seqpacket 0660 system system
writepid /dev/cpuset/system-background/tasks
在lmkd.rc中,启动了lmkd进程,并创建了一个名为lmkd的socket的描述符,用于socket进程间通信。lmkd启动后首先执行main方法。
int main(int argc __unused, char **argv __unused) {
struct sched_param param = {
.sched_priority = 1,
};
sched_setscheduler(0, SCHED_FIFO, ¶m);
if (!init())
mainloop();
}
main方法首先设置了当前进程的调度规则,然后执行了init方法和mainLoop方法。
static int init(void) {
struct epoll_event epev;
int i;
int ret;
//获取当前系统的页大小,单位kb
page_k = sysconf(_SC_PAGESIZE);
if (page_k == -1)
page_k = PAGE_SIZE;
page_k /= 1024;
// 创建一个epollfd描述符
epollfd = epoll_create(MAX_EPOLL_EVENTS);
if (epollfd == -1) {
ALOGE("epoll_create failed (errno=%d)", errno);
return -1;
}
// mark data connections as not connected
for (int i = 0; i < MAX_DATA_CONN; i++) {
data_sock[i].sock = -1;
}
// 获取init.rc中创建的lmkd socket描述符
ctrl_sock.sock = android_get_control_socket("lmkd");
if (ctrl_sock.sock < 0) {
ALOGE("get lmkd control socket failed");
return -1;
}
// 监听socket的连接,即ProcessList的Socket连接
ret = listen(ctrl_sock.sock, MAX_DATA_CONN);
if (ret < 0) {
ALOGE("lmkd control socket listen failed (errno=%d)", errno);
return -1;
}
// Epoll 设置监听socket中的可读事件,当有可读事件的时候回调ctrl_connect_hander方法
//处理socket连接过程
epev.events = EPOLLIN;
ctrl_sock.handler_info.handler = ctrl_connect_handler;
epev.data.ptr = (void *)&(ctrl_sock.handler_info);
if (epoll_ctl(epollfd, EPOLL_CTL_ADD, ctrl_sock.sock, &epev) ==