Android LMKD 服务深度解析
源码路径:
system/memory/lmkd/
1. LMKD 概述
1.1 什么是 LMKD
LMKD (Low Memory Killer Daemon) 是 Android 的用户态内存压力管理守护进程,负责在系统内存不足时选择并杀死低优先级进程以释放内存。
核心职责:
- 进程注册与管理 - 维护所有已注册进程的优先级信息
- 内存压力监控 - 通过 PSI (Pressure Stall Information) 监控内存压力
- 进程选择与杀死 - 根据 oom_adj 值选择合适的进程进行杀死
- 策略配置 - 接收 Framework 的 minfree/adj 配置
1.2 LMKD 架构图
┌─────────────────────────────────────────────────────────────┐
│ ActivityManagerService │
│ (OomAdjuster 计算进程 adj 值) │
└─────────────────────────────────────────────────────────────┘
│
│ setOomAdj(pid, uid, adj)
│ writeLmkd(ByteBuffer)
▼
┌─────────────────────────────────────────────────────────────┐
│ LmkdConnection (Java) │
│ Framework 侧 socket 连接管理 │
│ LocalSocket → "lmkd" socket (RESERVED namespace) │
└─────────────────────────────────────────────────────────────┘
│
│ SOCK_SEQPACKET
▼
┌─────────────────────────────────────────────────────────────┐
│ LMKD Daemon (C++) │
│ system/memory/lmkd/lmkd.cpp │
├─────────────────────────────────────────────────────────────┤
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ Socket Handler││ PSI Monitor │ │ Process Killer│ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
└─────────────────────────────────────────────────────────────┘
│
│ pidfd_open() + kill()
▼
┌─────────────────────────────────────────────────────────────┐
│ Target Process │
│ (被选中的低优先级进程) │
└─────────────────────────────────────────────────────────────┘
2. LMKD 服务启动流程
2.1 Init 配置文件 (lmkd.rc)
文件路径: system/memory/lmkd/lmkd.rc
service lmkd /system/bin/lmkd
class core
user lmkd
group lmkd system readproc
capabilities DAC_OVERRIDE KILL IPC_LOCK SYS_NICE SYS_RESOURCE
critical
socket lmkd seqpacket+passcred 0660 system system
task_profiles ServiceCapacityLow
on property:lmkd.reinit=1
exec_background /system/bin/lmkd --reinit
# 系统启动完成后重新初始化
on property:sys.boot_completed=1 && property:lmkd.reinit=0
setprop lmkd.reinit 1
关键配置说明:
| 配置项 | 说明 |
|---|---|
class core | 属于核心服务类,启动优先级高 |
user lmkd | 以 lmkd 用户身份运行 |
group lmkd system readproc | 允许读取进程信息 |
capabilities | DAC_OVERRIDE(文件权限), KILL(杀进程), IPC_LOCK(内存锁定), SYS_NICE(调度), SYS_RESOURCE(资源限制) |
socket lmkd seqpacket+passcred 0660 | 创建 SEQPACKET 类型 socket,传递 credentials |
critical | 关键服务,崩溃后会被重启 |
2.2 Socket 创建机制
Init 进程在启动 lmkd 服务时,根据 socket lmkd ... 配置自动创建 socket:
// init 进程中的 socket 创建逻辑
// socket 名称: lmkd
// 类型: SOCK_SEQPACKET (有序可靠数据包)
// 权限: 0660 (system:system 可读写)
// passcred: 发送时附带进程 credentials (uid/pid)
Socket 特性:
- SOCK_SEQPACKET: 有序、可靠、基于连接的数据包传输
- passcred: 每条消息附带发送者的 credentials,用于权限验证
- Namespace RESERVED:
/dev/socket/lmkd(abstract socket)
2.3 main() 函数启动流程
文件路径: system/memory/lmkd/lmkd.cpp:4234
int main(int argc, char **argv) {
// 1. 处理重新初始化请求
if ((argc > 1) && argv[1] && !strcmp(argv[1], "--reinit")) {
if (property_set(LMKD_REINIT_PROP, "")) {
ALOGE("Failed to reset " LMKD_REINIT_PROP " property");
}
return issue_reinit(); // 向已运行的 lmkd 发送重新初始化命令
}
// 2. 初始化配置属性
if (!update_props()) {
ALOGE("Failed to initialize props, exiting.");
return -1;
}
// 3. 创建日志上下文
ctx = create_android_logger(KILLINFO_LOG_TAG);
// 4. 初始化核心功能
if (!init()) {
// 用户态模式下的特殊设置
if (!use_inkernel_interface) {
// 锁定内存,防止被 swap (需要 CAP_IPC_LOCK)
if (mlockall(MCL_CURRENT | MCL_FUTURE | MCL_ONFAULT) && (errno != EINVAL)) {
ALOGW("mlockall failed %s", strerror(errno));
}
// 设置实时调度优先级 (需要 CAP_NICE)
struct sched_param param = { .sched_priority = 1 };
if (sched_setscheduler(0, SCHED_FIFO, ¶m)) {
ALOGW("set SCHED_FIFO failed %s", strerror(errno));
}
}
// 5. 初始化 Reaper (进程杀死线程池)
if (init_reaper()) {
ALOGI("Process reaper initialized with %d threads in the pool",
reaper.thread_cnt());
}
// 6. 初始化 Watchdog
if (!watchdog.init()) {
ALOGE("Failed to initialize the watchdog");
}
// 7. 进入主循环
mainloop();
}
android_log_destroy(&ctx);
ALOGI("exiting");
return 0;
}
2.4 init() 函数 - 核心初始化
文件路径: system/memory/lmkd/lmkd.cpp:3882
static int init(void) {
// 1. 创建 epoll 实例用于事件监听
epollfd = epoll_create(MAX_EPOLL_EVENTS);
if (epollfd == -1) {
ALOGE("epoll_create failed (errno=%d)", errno);
return -1;
}
// 2. 初始化数据连接状态
for (int i = 0; i < MAX_DATA_CONN; i++) {
data_sock[i].sock = -1; // 标记为未连接
}
// 3. 获取 init 创建的控制 socket ★★★ 关键步骤
ctrl_sock.sock = android_get_control_socket("lmkd");
if (ctrl_sock.sock < 0) {
ALOGE("get lmkd control socket failed");
return -1;
}
// 4. 开始监听连接请求
ret = listen(ctrl_sock.sock, MAX_DATA_CONN);
if (ret < 0) {
ALOGE("lmkd control socket listen failed (errno=%d)", errno);
return -1;
}
// 5. 注册 socket 连接事件处理器到 epoll
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) == -1) {
ALOGE("epoll_ctl for lmkd control socket failed (errno=%d)", errno);
return -1;
}
maxevents++;
// 6. 检查是否使用内核 LMK 接口
has_inkernel_module = !access(INKERNEL_MINFREE_PATH, W_OK);
use_inkernel_interface = has_inkernel_module;
if (use_inkernel_interface) {
ALOGI("Using in-kernel low memory killer interface");
// 使用内核接口的初始化...
} else {
// 用户态模式:初始化 PSI 监控器
if (!init_monitors()) {
return -1;
}
property_set("sys.lmk.reportkills", "1");
}
// 7. 初始化进程优先级哈希表
for (i = 0; i <= ADJTOSLOT(OOM_SCORE_ADJ_MAX); i++) {
procadjslot_list[i].next = &procadjslot_list[i];
procadjslot_list[i].prev = &procadjslot_list[i];
}
// 8. 检查 pidfd 支持
pidfd = TEMP_FAILURE_RETRY(pidfd_open(getpid(), 0));
pidfd_supported = (pidfd >= 0 || errno != ENOSYS);
ALOGI("Process polling is %s", pidfd_supported ? "supported" : "not supported");
return 0;
}
2.5 mainloop() - 主事件循环
文件路径: system/memory/lmkd/lmkd.cpp:4043
static void mainloop(void) {
struct event_handler_info* handler_info;
struct polling_params poll_params;
struct epoll_event *evt;
poll_params.poll_handler = NULL;
poll_params.paused_handler = NULL;
while (1) { // 无限循环
struct epoll_event events[MAX_EPOLL_EVENTS];
int nevents;
int i;
// 根据 polling 状态计算超时
if (poll_params.poll_handler) {
// 正在 polling 内存状态
delay = poll_params.polling_interval_ms;
nevents = epoll_wait(epollfd, events, maxevents, delay);
} else if (kill_timeout_ms && is_waiting_for_kill()) {
// 等待进程死亡通知
delay = kill_timeout_ms;
nevents = epoll_wait(epollfd, events, maxevents, delay);
} else {
// 正常等待事件,无超时
nevents = epoll_wait(epollfd, events, maxevents, -1);
}
if (nevents == -1) {
if (errno == EINTR) continue;
ALOGE("epoll_wait failed (errno=%d)", errno);
continue;
}
// 第一轮:处理连接断开事件 (EPOLLHUP)
for (i = 0, evt = &events[0]; i < nevents; ++i, evt++) {
if ((evt->events & EPOLLHUP) && evt->data.ptr) {
ALOGI("lmkd data connection dropped");
handler_info = (struct event_handler_info*)evt->data.ptr;
ctrl_data_close(handler_info->data); // 关闭数据连接
}
}
// 第二轮:处理其他事件
for (i = 0, evt = &events[0]; i < nevents; ++i, evt++) {
if (evt->events & EPOLLHUP) continue; // 已在第一轮处理
if (evt->data.ptr) {
handler_info = (struct event_handler_info*)evt->data.ptr;
call_handler(handler_info, &poll_params, evt->events);
}
}
}
}
3. Socket 通信流程
3.1 连接建立流程
┌─────────────────────────────────────────────────────────────┐
│ Framework (ProcessList.init) │
│ 创建 LmkdConnection 对象 │
└─────────────────────────────────────────────────────────────┘
│
│ sLmkdConnection.connect()
▼
┌─────────────────────────────────────────────────────────────┐
│ LmkdConnection.connect() │
│ LmkdConnection.java:122 │
├─────────────────────────────────────────────────────────────┤
│ 1. openSocket() - 创建 LocalSocket │
│ socket = new LocalSocket(SOCKET_SEQPACKET) │
│ socket.connect(new LocalSocketAddress("lmkd", RESERVED))│
│ │
│ 2. 获取 I/O streams │
│ ostream = socket.getOutputStream() │
│ istream = socket.getInputStream() │
│ │
│ 3. 执行 onConnect 回调 │
│ mListener.onConnect(ostream) │
│ → onLmkdConnect() 发送初始化命令 │
│ │
│ 4. 注册 FD 监听 │
│ mMsgQueue.addOnFileDescriptorEventListener() │
└─────────────────────────────────────────────────────────────┘
│
│ accept() → epoll IN event
▼
┌─────────────────────────────────────────────────────────────┐
│ ctrl_connect_handler() │
│ lmkd.cpp:1599 │
├─────────────────────────────────────────────────────────────┤
│ 1. 查找空闲数据连接槽位 │
│ free_dscock_idx = get_free_dsock() │
│ │
│ 2. accept 新连接 │
│ data_sock[idx].sock = accept(ctrl_sock.sock, NULL, NULL) │
│ │
│ 3. 注册数据 socket 到 epoll │
│ epoll_ctl(EPOLL_CTL_ADD, data_sock[idx].sock, &epev) │
│ handler = ctrl_data_handler │
│ │
│ ALOGI("lmkd data connection established") │
└─────────────────────────────────────────────────────────────┘
3.2 LmkdConnection.openSocket() 实现
文件路径: frameworks/base/services/core/java/com/android/server/am/LmkdConnection.java:249
private LocalSocket openSocket() {
final LocalSocket socket;
try {
// 创建 SEQPACKET 类型 socket
socket = new LocalSocket(LocalSocket.SOCKET_SEQPACKET);
// 连接到 lmkd socket (abstract namespace)
socket.connect(
new LocalSocketAddress("lmkd",
LocalSocketAddress.Namespace.RESERVED));
} catch (IOException ex) {
Slog.e(TAG, "Connection failed: " + ex.toString());
return null;
}
return socket;
}
关键点:
SOCKET_SEQPACKET: 与 init.rc 中定义的类型一致Namespace.RESERVED: 对应/dev/socket/目录下的 abstract socket- Socket 名称
"lmkd"由 init 进程创建
3.3 数据发送流程 (setOomAdj)
┌─────────────────────────────────────────────────────────────┐
│ OomAdjuster.applyOomAdjLSP() │
│ 计算 adj 后调用 setOomAdj │
└─────────────────────────────────────────────────────────────┘
│
│ ProcessList.setOomAdj(pid, uid, amt)
▼
┌─────────────────────────────────────────────────────────────┐
│ ProcessList.setOomAdj() │
│ ProcessList.java:1491 │
├─────────────────────────────────────────────────────────────┤
│ ByteBuffer buf = ByteBuffer.allocate(4 * 4); │
│ buf.putInt(LMK_PROCPRIO); // 命令码 = 1 │
│ buf.putInt(pid); // 进程 ID │
│ buf.putInt(uid); // 用户 ID │
│ buf.putInt(amt); // oom_adj 值 (-1000 ~ 1000) │
│ │
│ writeLmkd(buf, null); // 发送到 lmkd │
└─────────────────────────────────────────────────────────────┘
│
│ LmkdConnection.write(buf)
▼
┌─────────────────────────────────────────────────────────────┐
│ LmkdConnection.write() │
│ LmkdConnection.java:264 │
├─────────────────────────────────────────────────────────────┤
│ mLmkdOutputStream.write(buf.array(), 0, buf.position()) │
└─────────────────────────────────────────────────────────────┘
│
│ socket send (SEQPACKET)
▼
┌─────────────────────────────────────────────────────────────┐
│ ctrl_data_handler() │
│ lmkd.cpp:1583 │
├─────────────────────────────────────────────────────────────┤
│ EPOLLIN 事件触发 │
│ → ctrl_command_handler(data) │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ ctrl_command_handler() │
│ lmkd.cpp:1479 │
├─────────────────────────────────────────────────────────────┤
│ 1. ctrl_data_read() - 读取数据包 │
│ len = ctrl_data_read(dsock_idx, packet, size, &cred) │
│ │
│ 2. 解析命令 │
│ cmd = lmkd_pack_get_cmd(packet) // LMK_PROCPRIO │
│ nargs = len / sizeof(int) - 1 │
│ │
│ 3. 根据命令类型处理 │
│ switch(cmd) { │
│ case LMK_PROCPRIO: │
│ cmd_procprio(packet, nargs, &cred); │
│ break; │
│ ... │
│ } │
└─────────────────────────────────────────────────────────────┘
3.4 cmd_procprio() - 进程注册处理
文件路径: system/memory/lmkd/lmkd.cpp:1134
static void cmd_procprio(LMKD_CTRL_PACKET packet, int field_count, struct ucred *cred) {
struct proc *procp;
struct lmk_procprio params;
// 1. 解析数据包
lmkd_pack_get_procprio(packet, field_count, ¶ms);
// params.pid = packet[1]
// params.uid = packet[2]
// params.oomadj = packet[3]
// params.ptype = packet[4] (APP 或 SERVICE)
// 2. 验证 oomadj 值范围
if (params.oomadj < OOM_SCORE_ADJ_MIN || // -1000
params.oomadj > OOM_SCORE_ADJ_MAX) { // 1000
ALOGE("Invalid PROCPRIO oomadj argument %d", params.oomadj);
return;
}
// 3. 验证是线程组 leader
if (read_proc_status(params.pid, buf, sizeof(buf))) {
if (parse_status_tag(buf, PROC_STATUS_TGID_FIELD, &tgid) && tgid != params.pid) {
ALOGE("Attempt to register a task that is not a thread group leader");
return;
}
}
// 4. ★★★ 写入内核 oom_score_adj 文件 ★★★
snprintf(path, sizeof(path), "/proc/%d/oom_score_adj", params.pid);
snprintf(val, sizeof(val), "%d", params.oomadj);
if (!writefilestring(path, val, false)) {
ALOGW("Failed to open %s; process %d might have been killed", path, params.pid);
return;
}
// 5. 用户态模式:管理进程信息
if (!use_inkernel_interface) {
// 设置 memory cgroup soft limit
if (params.ptype == PROC_TYPE_APP && per_app_memcg) {
// 根据 oomadj 计算 soft_limit_mult
// 写入 memory.soft_limit_in_bytes
}
// 注册到进程哈希表
procp = pid_lookup(params.pid);
if (!procp) {
// 创建新的 proc 结构
procp = static_cast<struct proc*>(calloc(1, sizeof(struct proc)));
procp->pid = params.pid;
procp->uid = params.uid;
// ...
pid_insert(procp); // 插入哈希表
}
// 更新优先级
procp->oomadj = params.oomadj;
// 插入优先级排序链表
proc_insert(procp);
}
}
4. LMKD 命令协议
4.1 命令码定义
文件路径: system/memory/lmkd/include/lmkd.h:29
enum lmk_cmd {
LMK_TARGET = 0, /* 设置 minfree/adj 配置 */
LMK_PROCPRIO, /* 注册进程,设置 oom_adj (1) */
LMK_PROCREMOVE, /* 移除进程注册 (2) */
LMK_PROCPURGE, /* 清除所有注册 (3) */
LMK_GETKILLCNT, /* 获取杀死计数 (4) */
LMK_SUBSCRIBE, /* 订阅异步事件 (5) */
LMK_PROCKILL, /* 进程被杀死通知 (6) - unsolicited */
LMK_UPDATE_PROPS, /* 更新属性配置 (7) */
LMK_STAT_KILL_OCCURRED, /* 杀死事件统计通知 (8) */
LMK_STAT_STATE_CHANGED, /* 状态变化通知 (9) */
};
4.2 数据包格式
LMK_PROCPRIO (设置进程优先级)
┌──────────┬──────────┬──────────┬──────────┬──────────┐
│ 命令码 │ PID │ UID │ oomadj │ ptype │
│ (int) │ (int) │ (int) │ (int) │ (int) │
│ 1 │ pid │ uid │ adj值 │ APP/SVC │
└──────────┴──────────┴──────────┴──────────┴──────────┘
4 bytes 4 bytes 4 bytes 4 bytes 4 bytes
Framework 发送代码 (ProcessList.java:1491):
public static void setOomAdj(int pid, int uid, int amt) {
ByteBuffer buf = ByteBuffer.allocate(4 * 4);
buf.putInt(LMK_PROCPRIO); // 1
buf.putInt(pid);
buf.putInt(uid);
buf.putInt(amt);
writeLmkd(buf, null);
}
Native 端解析 (lmkd.h:115):
static inline void lmkd_pack_get_procprio(LMKD_CTRL_PACKET packet,
struct lmk_procprio* params) {
params->pid = (pid_t)ntohl(packet[1]);
params->uid = (uid_t)ntohl(packet[2]);
params->oomadj = ntohl(packet[3]);
params->ptype = (enum proc_type)ntohl(packet[4]);
}
LMK_TARGET (设置 minfree 配置)
┌──────────┬──────────┬──────────┬──────────┬─────┬──────────┬──────────┐
│ 命令码 │ minfree1 │ adj1 │ minfree2 │ adj2│ ... │ adjN │
│ 0 │ pages │ adj值 │ pages │adj值│ │ │
└──────────┴──────────┴──────────┴──────────┴─────┴──────────┴──────────┘
最多 6 组 (minfree, adj) 对
Framework 发送代码 (ProcessList.java:1545):
public boolean onLmkdConnect(OutputStream ostream) {
// ...
// Reset oom_adj levels
buf = ByteBuffer.allocate(4 * (2 * mOomAdj.length + 1));
buf.putInt(LMK_TARGET);
for (int i = 0; i < mOomAdj.length; i++) {
buf.putInt((mOomMinFree[i] * 1024)/PAGE_SIZE); // minfree (pages)
buf.putInt(mOomAdj[i]); // adj
}
ostream.write(buf.array(), 0, buf.position());
}
LMK_PROCREMOVE (移除进程)
┌──────────┬──────────┐
│ 命令码 │ PID │
│ 2 │ pid │
└──────────┴──────────┘
Framework 发送代码 (ProcessList.java:1516):
public static final void remove(int pid) {
ByteBuffer buf = ByteBuffer.allocate(4 * 2);
buf.putInt(LMK_PROCREMOVE);
buf.putInt(pid);
writeLmkd(buf, null);
}
LMK_SUBSCRIBE (订阅事件)
┌──────────┬──────────┐
│ 命令码 │ 事件类型 │
│ 5 │ evt_type │
└──────────┴──────────┘
事件类型:
LMK_ASYNC_EVENT_KILL (0)- 进程被杀死事件LMK_ASYNC_EVENT_STAT (1)- 统计事件
5. Framework 侧 LmkdConnection 实现
5.1 类结构
文件路径: frameworks/base/services/core/java/com/android/server/am/LmkdConnection.java
public class LmkdConnection {
// Socket 和 I/O 流
private LocalSocket mLmkdSocket = null;
private OutputStream mLmkdOutputStream = null;
private InputStream mLmkdInputStream = null;
// 输入数据缓冲区
private final ByteBuffer mInputBuf = ByteBuffer.allocate(LMKD_REPLY_MAX_SIZE);
// 回调监听器
interface LmkdConnectionListener {
boolean onConnect(OutputStream ostream); // 连接建立回调
void onDisconnect(); // 连接断开回调
boolean isReplyExpected(...); // 响应匹配检查
boolean handleUnsolicitedMessage(...); // 处理异步消息
}
private final LmkdConnectionListener mListener;
}
5.2 连接管理流程
文件路径: ProcessList.java:864
void init(ActivityManagerService service, ...) {
// ...
if (sKillHandler == null) {
sKillThread = new ServiceThread(TAG + ":kill", THREAD_PRIORITY_BACKGROUND, true);
sKillThread.start();
sKillHandler = new KillHandler(sKillThread.getLooper());
// 创建 LmkdConnection
sLmkdConnection = new LmkdConnection(sKillThread.getLooper().getQueue(),
new LmkdConnection.LmkdConnectionListener() {
@Override
public boolean onConnect(OutputStream ostream) {
Slog.i(TAG, "Connection with lmkd established");
return onLmkdConnect(ostream); // 发送初始化命令
}
@Override
public void onDisconnect() {
Slog.w(TAG, "Lost connection to lmkd");
// 重连机制:延迟后重试
sKillHandler.sendMessageDelayed(
sKillHandler.obtainMessage(KillHandler.LMKD_RECONNECT_MSG),
LMKD_RECONNECT_DELAY_MS);
}
@Override
public boolean handleUnsolicitedMessage(DataInputStream inputData, int receivedLen) {
// 处理 LMK_PROCKILL 等异步通知
switch (inputData.readInt()) {
case LMK_PROCKILL:
int pid = inputData.readInt();
int uid = inputData.readInt();
mAppExitInfoTracker.scheduleNoteLmkdProcKilled(pid, uid);
return true;
case LMK_KILL_OCCURRED:
LmkdStatsReporter.logKillOccurred(inputData, ...);
return true;
// ...
}
return false;
}
}
);
}
}
5.3 onLmkdConnect() 初始化命令
文件路径: ProcessList.java:1545
public boolean onLmkdConnect(OutputStream ostream) {
try {
// 1. 清除所有已注册进程
ByteBuffer buf = ByteBuffer.allocate(4);
buf.putInt(LMK_PROCPURGE);
ostream.write(buf.array(), 0, buf.position());
// 2. 重新设置 minfree/adj 配置
if (mOomLevelsSet) {
buf = ByteBuffer.allocate(4 * (2 * mOomAdj.length + 1));
buf.putInt(LMK_TARGET);
for (int i = 0; i < mOomAdj.length; i++) {
buf.putInt((mOomMinFree[i] * 1024)/PAGE_SIZE);
buf.putInt(mOomAdj[i]);
}
ostream.write(buf.array(), 0, buf.position());
}
// 3. 订阅进程杀死事件
buf = ByteBuffer.allocate(4 * 2);
buf.putInt(LMK_SUBSCRIBE);
buf.putInt(LMK_ASYNC_EVENT_KILL);
ostream.write(buf.array(), 0, buf.position());
// 4. 订阅统计事件
buf = ByteBuffer.allocate(4 * 2);
buf.putInt(LMK_SUBSCRIBE);
buf.putInt(LMK_ASYNC_EVENT_STAT);
ostream.write(buf.array(), 0, buf.position());
} catch (IOException ex) {
return false;
}
return true;
}
5.4 writeLmkd() 发送函数
文件路径: ProcessList.java:1578
private static boolean writeLmkd(ByteBuffer buf, ByteBuffer repl) {
if (!sLmkdConnection.isConnected()) {
// 连接断开,触发重连
sKillHandler.sendMessage(
sKillHandler.obtainMessage(KillHandler.LMKD_RECONNECT_MSG));
// 等待连接,最多 3 次 (约 3 秒)
for (int retry = 0; retry < 3; retry++) {
if (sLmkdConnection.waitForConnection(LMKD_RECONNECT_DELAY_MS)) {
break;
}
}
if (!sLmkdConnection.isConnected()) {
return false;
}
}
// 发送数据
if (repl != null) {
// 需要响应的请求
return sLmkdConnection.exchange(buf, repl);
} else {
// 无需响应的请求
return sLmkdConnection.write(buf);
}
}
6. Native 侧 liblmkd_utils
6.1 工具函数
文件路径: system/memory/lmkd/liblmkd_utils.cpp
// 连接到 lmkd socket
int lmkd_connect() {
return socket_local_client("lmkd",
ANDROID_SOCKET_NAMESPACE_RESERVED,
SOCK_SEQPACKET | SOCK_CLOEXEC);
}
// 注册进程
int lmkd_register_proc(int sock, struct lmk_procprio *params) {
LMKD_CTRL_PACKET packet;
size_t size;
size = lmkd_pack_set_procprio(packet, params);
ret = TEMP_FAILURE_RETRY(write(sock, packet, size));
return (ret < 0) ? -1 : 0;
}
// 移除进程注册
int lmkd_unregister_proc(int sock, struct lmk_procremove *params) {
LMKD_CTRL_PACKET packet;
size_t size;
size = lmkd_pack_set_procremove(packet, params);
ret = TEMP_FAILURE_RETRY(write(sock, packet, size));
return (ret < 0) ? -1 : 0;
}
6.2 init 进程中的服务注册
文件路径: system/core/init/lmkd_service.cpp
static int lmkd_socket = -1;
static LmkdRegistrationResult RegisterProcess(uid_t uid, pid_t pid, int oom_score_adjust) {
// 连接 lmkd
if (lmkd_socket < 0) {
lmkd_socket = lmkd_connect();
if (lmkd_socket < 0) {
return LMKD_CONN_FAILED;
}
}
// 注册服务进程
struct lmk_procprio params;
params.pid = pid;
params.uid = uid;
params.oomadj = oom_score_adjust;
params.ptype = PROC_TYPE_SERVICE; // 服务类型
if (lmkd_register_proc(lmkd_socket, ¶ms) != 0) {
close(lmkd_socket);
lmkd_socket = -1;
return LMKD_REG_FAILED;
}
return LMKD_REG_SUCCESS;
}
// init 进程调用此函数注册服务
void LmkdRegister(const std::string& name, uid_t uid, pid_t pid, int oom_score_adjust) {
LmkdRegistrationResult result;
result = RegisterProcess(uid, pid, oom_score_adjust);
// ...
}
7. 进程杀死流程
7.1 PSI 内存压力监控
文件路径: lmkd.cpp PSI 监控器
// PSI 阈值配置
static struct psi_threshold psi_thresholds[VMPRESS_LEVEL_COUNT] = {
{ PSI_SOME, 70 }, // 70ms partial stall - LOW pressure
{ PSI_SOME, 100 }, // 100ms partial stall - MEDIUM pressure
{ PSI_FULL, 70 }, // 70ms complete stall - CRITICAL pressure
};
// PSI 事件触发时查找并杀死进程
static void mp_event_handler(int data, uint32_t events, struct polling_params *poll_params) {
// 1. 评估内存压力等级
// 2. 根据压力等级选择合适的 adj 阈值
// 3. 从进程链表中查找符合条件的进程
// 4. 调用 kill_one_process() 杀死进程
}
7.2 进程选择策略
// 从最低优先级开始查找
struct proc *procp;
for (int i = OOM_SCORE_ADJ_MAX; i >= target_oomadj; i--) {
procp = procadjslot_list[i].next;
while (procp != &procadjslot_list[i]) {
// 检查进程是否可杀死
if (procp->oomadj >= target_oomadj && procp->pid > 0) {
// 执行杀死
kill_one_process(procp);
return;
}
procp = procp->next;
}
}
7.3 进程杀死执行
static void kill_one_process(struct proc *procp) {
int pid = procp->pid;
int pidfd = procp->pidfd;
// 发送 SIGKILL
if (pidfd >= 0) {
// 使用 pidfd 发送信号 (更可靠)
syscall(__NR_pidfd_send_signal, pidfd, SIGKILL, NULL, 0);
} else {
// 传统方式
kill(pid, SIGKILL);
}
// 记录杀死信息
last_kill_pid_or_fd = pidfd >= 0 ? pidfd : pid;
clock_gettime(CLOCK_MONOTONIC_COARSE, &last_kill_tm);
// 通知订阅者 (LMK_PROCKILL)
notify_kill(pid, procp->uid);
}
8. 关键代码路径汇总
8.1 LMKD Native 侧
| 文件 | 路径 | 关键内容 |
|---|---|---|
| 主程序 | system/memory/lmkd/lmkd.cpp | main(), init(), mainloop(), cmd_* 处理 |
| 头文件 | system/memory/lmkd/include/lmkd.h | 命令码定义, 数据包格式 |
| Init配置 | system/memory/lmkd/lmkd.rc | 服务启动配置, socket 创建 |
| 工具库 | system/memory/lmkd/liblmkd_utils.cpp | lmkd_connect(), lmkd_register_proc() |
| Init服务 | system/core/init/lmkd_service.cpp | 服务进程注册 |
| Reaper | system/memory/lmkd/reaper.cpp | 进程杀死线程池 |
8.2 Framework 侧
| 文件 | 路径 | 关键内容 |
|---|---|---|
| ProcessList | frameworks/base/services/.../am/ProcessList.java | setOomAdj(), writeLmkd(), onLmkdConnect() |
| LmkdConnection | frameworks/base/services/.../am/LmkdConnection.java | Socket 连接管理, 数据收发 |
| OomAdjuster | frameworks/base/services/.../am/OomAdjuster.java | adj 计算, applyOomAdjLSP() |
8.3 关键函数行号
| 函数 | 文件 | 行号 |
|---|---|---|
main() | lmkd.cpp | 4234 |
init() | lmkd.cpp | 3882 |
mainloop() | lmkd.cpp | 4043 |
ctrl_connect_handler() | lmkd.cpp | 1599 |
ctrl_command_handler() | lmkd.cpp | 1479 |
cmd_procprio() | lmkd.cpp | 1134 |
android_get_control_socket() | lmkd.cpp | 3909 |
LmkdConnection.connect() | LmkdConnection.java | 122 |
openSocket() | LmkdConnection.java | 249 |
setOomAdj() | ProcessList.java | 1491 |
writeLmkd() | ProcessList.java | 1578 |
onLmkdConnect() | ProcessList.java | 1545 |
9. 完整通信流程图
┌──────────────────────────────────────────────────────────────────────────────┐
│ 系统启动阶段 │
├──────────────────────────────────────────────────────────────────────────────┤
│ init 进程 │
│ │ │
│ ├─ 解析 lmkd.rc │
│ │ └─ 创建 socket: "/dev/socket/lmkkd" (SOCK_SEQPACKET) │
│ │ │
│ ├─ 启动 lmkd 服务 │
│ │ └─ execve("/system/bin/lmkkd") │
│ │ │
│ └─ 注册 init 服务进程 │
│ └─ LmkdRegister() → lmkd_socket → LMK_PROCPRIO │
└──────────────────────────────────────────────────────────────────────────────┘
┌──────────────────────────────────────────────────────────────────────────────┐
│ LMKD 初始化阶段 │
├──────────────────────────────────────────────────────────────────────────────┤
│ lmkd main() │
│ │ │
│ ├─ update_props() - 读取配置属性 │
│ │ │
│ ├─ init() │
│ │ ├─ epoll_create() │
│ │ ├─ android_get_control_socket("lmkd") ← 获取 init 创建的 socket │
│ │ ├─ listen(socket, MAX_DATA_CONN) │
│ │ ├─ epoll_ctl(EPOLL_CTL_ADD, socket, ctrl_connect_handler) │
│ │ └─ init_monitors() - 初始化 PSI 监控 │
│ │ │
│ └─ mainloop() │
│ └─ epoll_wait() 等待事件 │
└──────────────────────────────────────────────────────────────────────────────┘
┌──────────────────────────────────────────────────────────────────────────────┐
│ Framework 连接阶段 │
├──────────────────────────────────────────────────────────────────────────────┤
│ ActivityManagerService.init() │
│ │ │
│ ├─ ProcessList.init() │
│ │ └─ 创建 LmkdConnection │
│ │ │
│ ├─ LmkdConnection.connect() │
│ │ ├─ openSocket() │
│ │ │ └─ new LocalSocket(SOCKET_SEQPACKET) │
│ │ │ └─ connect(new LocalSocketAddress("lmkd", RESERVED)) │
│ │ │ │
│ │ ├─ 获取 I/O streams │
│ │ │ │
│ │ ├─ onLmkdConnect(ostream) │
│ │ │ ├─ LMK_PROCPURGE │
│ │ │ ├─ LMK_TARGET (minfree/adj 配置) │
│ │ │ ├─ LMK_SUBSCRIBE (KILL) │
│ │ │ └─ LMK_SUBSCRIBE (STAT) │
│ │ │ │
│ │ └─ 注册 FD 监听事件 │
│ │ │
│ └─ lmkd 收到连接 │
│ ├─ epoll_wait() 返回 EPOLLIN │
│ ├─ ctrl_connect_handler() │
│ │ └─ accept(socket) → 新 data socket │
│ │ └─ epoll_ctl(EPOLL_CTL_ADD, data_sock, ctrl_data_handler) │
│ └─ ALOGI("lmkd data connection established") │
└──────────────────────────────────────────────────────────────────────────────┘
┌──────────────────────────────────────────────────────────────────────────────┐
│ 运行时 adj 更新 │
├──────────────────────────────────────────────────────────────────────────────┤
│ OomAdjuster.computeOomAdjLSP() → applyOomAdjLSP() │
│ │ │
│ ├─ ProcessList.setOomAdj(pid, uid, amt) │
│ │ └─ ByteBuffer: [LMK_PROCPRIO, pid, uid, adj] │
│ │ └─ writeLmkd(buf, null) │
│ │ │
│ ├─ LmkdConnection.write() │
│ │ └─ mLmkdOutputStream.write(buf.array()) │
│ │ │
│ └─ lmkd 收到命令 │
│ ├─ epoll_wait() 返回 EPOLLIN │
│ ├─ ctrl_data_handler(data_sock_idx) │
│ ├─ ctrl_command_handler() │
│ │ ├─ ctrl_data_read() → packet │
│ │ ├─ lmkd_pack_get_cmd() → LMK_PROCPRIO │
│ │ └─ cmd_procprio() │
│ │ ├─ lmkd_pack_get_procprio() → 解析参数 │
│ │ ├─ writefilestring("/proc/pid/oom_score_adj", adj) │
│ │ ├─ pid_insert() → 注册到哈希表 │
│ │ └─ proc_insert() → 插入优先级链表 │
│ └─ 返回 │
└──────────────────────────────────────────────────────────────────────────────┘
┌──────────────────────────────────────────────────────────────────────────────┐
│ 内存压力 → 进程杀死 │
├──────────────────────────────────────────────────────────────────────────────┤
│ PSI 监控器 │
│ │ │
│ ├─ PSI 事件触发 (内存压力超过阈值) │
│ │ │
│ ├─ mp_event_handler() │
│ │ ├─ 读取内存状态 │
│ │ ├─ 计算需要释放的内存量 │
│ │ ├─ 确定目标 adj 阈值 │
│ │ └─ 从进程链表查找符合条件的进程 │
│ │ │
│ ├─ kill_one_process() │
│ │ ├─ pidfd_send_signal(pidfd, SIGKILL) 或 kill(pid, SIGKILL) │
│ │ └─ notify_kill(pid, uid) → 发送 LMK_PROCKILL 通知 │
│ │ │
│ └─ Framework 收到通知 │
│ ├─ fileDescriptorEventHandler() │
│ ├─ processIncomingData() │
│ ├─ handleUnsolicitedMessage() │
│ │ └─ LMK_PROCKILL → scheduleNoteLmkdProcKilled() │
│ └─ 记录进程退出信息 │
└──────────────────────────────────────────────────────────────────────────────┘
参考文献
-
LMKD 源码
system/memory/lmkd/lmkd.cpp- 主程序system/memory/lmkd/include/lmkd.h- 协议定义system/memory/lmkd/liblmkd_utils.cpp- 工具库system/memory/lmkd/lmkd.rc- Init 配置
-
Framework 源码
frameworks/base/services/core/java/com/android/server/am/ProcessList.javaframeworks/base/services/core/java/com/android/server/am/LmkdConnection.javaframeworks/base/services/core/java/com/android/server/am/OomAdjuster.java
-
Init 服务注册
system/core/init/lmkd_service.cpp
-
Android 官方文档
- PSI (Pressure Stall Information) 监控
- Low Memory Killer 设计文档
文档创建日期: 2026/04/28