/* * Supported LMKD commands */ enumlmk_cmd { LMK_TARGET = 0, /* Associate minfree with oom_adj_score */ LMK_PROCPRIO, /* Register a process and set its oom_adj_score */ LMK_PROCREMOVE, /* Unregister a process */ LMK_PROCPURGE, /* Purge all registered processes */ LMK_GETKILLCNT, /* Get number of kills */ LMK_SUBSCRIBE, /* Subscribe for asynchronous events */ LMK_PROCKILL, /* Unsolicited msg to subscribed clients on proc kills */ LMK_UPDATE_PROPS, /* Reinit properties */ };
publicstaticvoidsetOomAdj(int pid, int uid, int amt){ // This indicates that the process is not started yet and so no need to proceed further. if (pid <= 0) { return; } if (amt == UNKNOWN_ADJ) return; long start = SystemClock.elapsedRealtime(); // 将进程一些信息放进ByteBuffer ByteBuffer buf = ByteBuffer.allocate(4 * 4); buf.putInt(LMK_PROCPRIO); buf.putInt(pid); buf.putInt(uid); buf.putInt(amt); // 写入socket缓冲区,准备发送 writeLmkd(buf, null); long now = SystemClock.elapsedRealtime(); if ((now-start) > 250) { Slog.w("ActivityManager", "SLOW OOM ADJ: " + (now-start) + "ms for pid " + pid + " = " + amt); } }
writeLmkd
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
privatestaticbooleanwriteLmkd(ByteBuffer buf, ByteBuffer repl){ // isConnected,此方法是主要,监测socket是否创建连接 if (!sLmkdConnection.isConnected()) { // try to connect immediately and then keep retrying sKillHandler.sendMessage( sKillHandler.obtainMessage(KillHandler.LMKD_RECONNECT_MSG)); // wait for connection retrying 3 times (up to 3 seconds) if (!sLmkdConnection.waitForConnection(3 * LMKD_RECONNECT_DELAY_MS)) { returnfalse; } } // 发送消息 return sLmkdConnection.exchange(buf, repl); }
/* Second pass to handle all other events */ for (i = 0, evt = &events[0]; i < nevents; ++i, evt++) { if (evt->events & EPOLLERR) { ALOGD("EPOLLERR on event #%d", i); } if (evt->events & EPOLLHUP) { /* This case was handled in the first pass */ continue; } if (evt->data.ptr) { // 接收到消息,调用回调方法 handler_info = (struct event_handler_info*)evt->data.ptr; call_handler(handler_info, &poll_params, evt->events); } }
staticvoidcmd_procprio(LMKD_CTRL_PACKET packet, int field_count, struct ucred *cred){ ...... // 将adj的值写入到/proc/%d/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; errno=%d: process %d might have been killed", path, errno, params.pid); /* If this file does not exist the process is dead. */ return; }
if (use_inkernel_interface) { stats_store_taskname(params.pid, proc_get_name(params.pid, path, sizeof(path))); return; } ......
// 通过循环从数组的链表中找到进程的节点 procp = pid_lookup(params.pid); if (!procp) { // 进程节点为null则创建一个节点 int pidfd = -1;
if (pidfd_supported) { pidfd = TEMP_FAILURE_RETRY(sys_pidfd_open(params.pid, 0)); if (pidfd < 0) { ALOGE("pidfd_open for pid %d failed; errno=%d", params.pid, errno); return; } }
procp = static_cast<struct proc*>(calloc(1, sizeof(struct proc))); if (!procp) { // Oh, the irony. May need to rebuild our state. return; } procp->pid = params.pid; procp->pidfd = pidfd; procp->uid = params.uid; procp->reg_pid = cred->pid; procp->oomadj = params.oomadj; proc_insert(procp); } else { // 进程节点不为null则更新节点adj的值 if (!claim_record(procp, cred->pid)) { char buf[LINE_MAX]; /* Only registrant of the record can remove it */ ALOGE("%s (%d, %d) attempts to modify a process registered by another client", proc_get_name(cred->pid, buf, sizeof(buf)), cred->uid, cred->pid); return; } proc_unslot(procp); // 更新当前节点adj procp->oomadj = params.oomadj; proc_slot(procp); } }
privatefinalint[] mOomMinFreeLow = newint[] { 12288, 18432, 24576, 36864, 43008, 49152 }; // These are the high-end OOM level limits. This is appropriate for a // 1280x800 or larger screen with around 1GB RAM. Values are in KB. privatefinalint[] mOomMinFreeHigh = newint[] { 73728, 92160, 110592, 129024, 147456, 184320 };
privatevoidupdateOomLevels(int displayWidth, int displayHeight, boolean write){ // 根据屏幕分辨率计算minfree // Scale buckets from avail memory: at 300MB we use the lowest values to // 700MB or more for the top values. float scaleMem = ((float) (mTotalMemMb - 350)) / (700 - 350); 831 // Scale buckets from screen size. int minSize = 480 * 800; // 384000 int maxSize = 1280 * 800; // 1024000 230400 870400 .264 float scaleDisp = ((float)(displayWidth * displayHeight) - minSize) / (maxSize - minSize); if (false) { Slog.i("XXXXXX", "scaleMem=" + scaleMem); Slog.i("XXXXXX", "scaleDisp=" + scaleDisp + " dw=" + displayWidth + " dh=" + displayHeight); }
float scale = scaleMem > scaleDisp ? scaleMem : scaleDisp; if (scale < 0) scale = 0; elseif (scale > 1) scale = 1; int minfree_adj = Resources.getSystem().getInteger( com.android.internal.R.integer.config_lowMemoryKillerMinFreeKbytesAdjust); int minfree_abs = Resources.getSystem().getInteger( com.android.internal.R.integer.config_lowMemoryKillerMinFreeKbytesAbsolute); if (false) { Slog.i("XXXXXX", "minfree_adj=" + minfree_adj + " minfree_abs=" + minfree_abs); } finalboolean is64bit = Build.SUPPORTED_64_BIT_ABIS.length > 0; // 以下逻辑主要是更新minfree for (int i = 0; i < mOomAdj.length; i++) { int low = mOomMinFreeLow[i]; int high = mOomMinFreeHigh[i]; if (is64bit) { // Increase the high min-free levels for cached processes for 64-bit if (i == 4) high = (high * 3) / 2; elseif (i == 5) high = (high * 7) / 4; } mOomMinFree[i] = (int)(low + ((high - low) * scale)); } if (minfree_abs >= 0) { for (int i = 0; i < mOomAdj.length; i++) { mOomMinFree[i] = (int)((float)minfree_abs * mOomMinFree[i] / mOomMinFree[mOomAdj.length - 1]); } }
if (minfree_adj != 0) { for (int i = 0; i < mOomAdj.length; i++) { mOomMinFree[i] += (int)((float) minfree_adj * mOomMinFree[i] / mOomMinFree[mOomAdj.length - 1]); if (mOomMinFree[i] < 0) { mOomMinFree[i] = 0; } } }
// The maximum size we will restore a process from cached to background, when under // memory duress, is 1/3 the size we have reserved for kernel caches and other overhead // before killing background processes. mCachedRestoreLevel = (getMemLevel(ProcessList.CACHED_APP_MAX_ADJ) / 1024) / 3;
// Ask the kernel to try to keep enough memory free to allocate 3 full // screen 32bpp buffers without entering direct reclaim. int reserve = displayWidth * displayHeight * 4 * 3 / 1024; int reserve_adj = Resources.getSystem().getInteger( com.android.internal.R.integer.config_extraFreeKbytesAdjust); int reserve_abs = Resources.getSystem().getInteger( com.android.internal.R.integer.config_extraFreeKbytesAbsolute);
if (reserve_abs >= 0) { reserve = reserve_abs; } if (reserve_adj != 0) { reserve += reserve_adj; if (reserve < 0) { reserve = 0; } } // 通过socket将信息发送到native层LMKD if (write) { ByteBuffer buf = ByteBuffer.allocate(4 * (2 * mOomAdj.length + 1)); // 推送LMK_TARGET指令 buf.putInt(LMK_TARGET); for (int i = 0; i < mOomAdj.length; i++) { buf.putInt((mOomMinFree[i] * 1024)/PAGE_SIZE); buf.putInt(mOomAdj[i]); }
if (!app.isPersistent() || app.isolated) { if (DEBUG_PROCESSES || DEBUG_CLEANUP) Slog.v(TAG_CLEANUP, "Removing non-persistent process during cleanup: " + app); if (!replacingPid) { // 此处为重要点,调用ProcessList中的移除方法 mProcessList.removeProcessNameLocked(app.processName, app.uid, app); } mAtmInternal.clearHeavyWeightProcessIfEquals(app.getWindowProcessController()); } elseif (!app.removed) { // This app is persistent, so we need to keep its record around. // If it is not already on the pending app list, add it there // and start a new process for it. if (mPersistentStartingProcesses.indexOf(app) < 0) { mPersistentStartingProcesses.add(app); restart = true; } }
ProcessList.removeProcessNameLocked
1 2 3 4 5 6 7 8 9 10 11 12 13
@GuardedBy("mService") final ProcessRecord removeProcessNameLocked(final String name, final int uid, final ProcessRecord expecting) { ...... if ((expecting == null) || (old == expecting)) { // 通信native层LMKD mProcessNames.remove(name, uid); } ...... }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
final MyProcessMap mProcessNames = new MyProcessMap();
final class MyProcessMap extends ProcessMap<ProcessRecord> { @Override public ProcessRecord put(String name, int uid, ProcessRecord value) { final ProcessRecord r = super.put(name, uid, value); mService.mAtmInternal.onProcessAdded(r.getWindowProcessController()); return r; } @Override public ProcessRecord remove(String name, int uid) { // 调用remove方法 final ProcessRecord r = super.remove(name, uid); mService.mAtmInternal.onProcessRemoved(name, uid); return r; }
remove
1 2 3 4 5 6 7 8 9 10 11 12
public static final void remove(int pid) { // This indicates that the process is not started yet and so no need to proceed further. if (pid <= 0) { return; } ByteBuffer buf = ByteBuffer.allocate(4 * 2); // 发送指令,进行通信 buf.putInt(LMK_PROCREMOVE); buf.putInt(pid); writeLmkd(buf, null); }