Android中杀进程的几种方法 - killBackgroundProcesses
Posted Jtag特工
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android中杀进程的几种方法 - killBackgroundProcesses相关的知识,希望对你有一定的参考价值。
android中杀进程的几种方法 (1) - killBackgroundProcesses
ActivityManager中提供了几种方式来杀进程,比如有forceStopPackage、removeTask、killBackgroundProcesses等。
下面我们就来看看它们的背后都做了些什么。
removeTask
我们之前已经写了一篇《关于Android的浅杀》来介绍这个方法的变迁,大家可以回忆一下找找感觉。
复习一下removeTask的好处是,相对后面几个,它的逻辑要简单得多。
killBackgroundProcesses
ActivityManager中的killBackgroundProcesses
这是目前(截止至API24)唯一官方公开建议使用的方法,其它的都是隐藏的API。
我们先看一张这个API背后调用的简图:
另外有一个被废弃的restartPackage方法,现在只是killBackgroundProcesses的马甲。
2400 @Deprecated
2401 public void restartPackage(String packageName)
2402 killBackgroundProcesses(packageName);
2403
调用killBackgroundProcesses需要权限android.Manifest.permission.KILL_BACKGROUND_PROCESSES
按照惯例,这个方法肯定是通过IPC调用到AMS中:
2418 public void killBackgroundProcesses(String packageName)
2419 try
2420 ActivityManagerNative.getDefault().killBackgroundProcesses(packageName,
2421 UserHandle.myUserId());
2422 catch (RemoteException e)
2423
2424
AMS中的killBackgroundProcesses
我们直接来看AMS中的killBackgroundProcesses:
5202 @Override
5203 public void killBackgroundProcesses(final String packageName, int userId)
首先就是检查KILL_BACKGROUND_PROCESSES的权限:
5204 if (checkCallingPermission(android.Manifest.permission.KILL_BACKGROUND_PROCESSES)
5205 != PackageManager.PERMISSION_GRANTED &&
5206 checkCallingPermission(android.Manifest.permission.RESTART_PACKAGES)
5207 != PackageManager.PERMISSION_GRANTED)
5208 String msg = "Permission Denial: killBackgroundProcesses() from pid="
5209 + Binder.getCallingPid()
5210 + ", uid=" + Binder.getCallingUid()
5211 + " requires " + android.Manifest.permission.KILL_BACKGROUND_PROCESSES;
5212 Slog.w(TAG, msg);
5213 throw new SecurityException(msg);
5214
5215
下面正式开始干活:
5216 userId = handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
5217 userId, true, ALLOW_FULL_ONLY, "killBackgroundProcesses", null);
5218 long callingId = Binder.clearCallingIdentity();
5219 try
5220 IPackageManager pm = AppGlobals.getPackageManager();
5221 synchronized(this)
5222 int appId = -1;
5223 try
5224 appId = UserHandle.getAppId(pm.getPackageUid(packageName, 0));
5225 catch (RemoteException e)
5226
5227 if (appId == -1)
5228 Slog.w(TAG, "Invalid packageName: " + packageName);
5229 return;
5230
真正的逻辑都在killPackageProcessesLocked中。调用进来的时候只有包名和用户ID两个参数,但是killPackageProcessesLocked却搞出来9个参数。
5231 killPackageProcessesLocked(packageName, appId, userId,
5232 ProcessList.SERVICE_ADJ, false, true, true, false, "kill background");
5233
5234 finally
5235 Binder.restoreCallingIdentity(callingId);
5236
5237
AMS的killPackageProcessesLocked
5541 private final boolean killPackageProcessesLocked(String packageName, int appId,
5542 int userId, int minOomAdj, boolean callerWillRestart, boolean allowRestart,
5543 boolean doit, boolean evenPersistent, String reason)
5544 ArrayList<ProcessRecord> procs = new ArrayList<>();
5545
5546 // Remove all processes this package may have touched: all with the
5547 // same UID (except for the system or root user), and all whose name
5548 // matches the package name.
5549 final int NP = mProcessNames.getMap().size();
5550 for (int ip=0; ip<NP; ip++)
5551 SparseArray<ProcessRecord> apps = mProcessNames.getMap().valueAt(ip);
5552 final int NA = apps.size();
5553 for (int ia=0; ia<NA; ia++)
5554 ProcessRecord app = apps.valueAt(ia);
5555 if (app.persistent && !evenPersistent)
5556 // we don't kill persistent processes
5557 continue;
5558
5559 if (app.removed)
5560 if (doit)
5561 procs.add(app);
5562
5563 continue;
5564
5565
5566 // Skip process if it doesn't meet our oom adj requirement.
5567 if (app.setAdj < minOomAdj)
5568 continue;
5569
5570
5571 // If no package is specified, we call all processes under the
5572 // give user id.
5573 if (packageName == null)
5574 if (userId != UserHandle.USER_ALL && app.userId != userId)
5575 continue;
5576
5577 if (appId >= 0 && UserHandle.getAppId(app.uid) != appId)
5578 continue;
5579
5580 // Package has been specified, we want to hit all processes
5581 // that match it. We need to qualify this by the processes
5582 // that are running under the specified app and user ID.
5583 else
5584 final boolean isDep = app.pkgDeps != null
5585 && app.pkgDeps.contains(packageName);
5586 if (!isDep && UserHandle.getAppId(app.uid) != appId)
5587 continue;
5588
5589 if (userId != UserHandle.USER_ALL && app.userId != userId)
5590 continue;
5591
5592 if (!app.pkgList.containsKey(packageName) && !isDep)
5593 continue;
5594
5595
5596
5597 // Process has passed all conditions, kill it!
5598 if (!doit)
5599 return true;
5600
5601 app.removed = true;
5602 procs.add(app);
5603
5604
前面各种条件都准备好了之后,针对每一个proc去调用removeProcessLocked.
5606 int N = procs.size();
5607 for (int i=0; i<N; i++)
5608 removeProcessLocked(procs.get(i), callerWillRestart, allowRestart, reason);
5609
5610 updateOomAdjLocked();
5611 return N > 0;
5612
AMS之removeProcessLocked(4)
5916 private final boolean removeProcessLocked(ProcessRecord app,
5917 boolean callerWillRestart, boolean allowRestart, String reason)
5918 final String name = app.processName;
5919 final int uid = app.uid;
...
下面再调用两个参数的removeProcessNameLocked.
5923 removeProcessNameLocked(name, uid);
5924 if (mHeavyWeightProcess == app)
5925 mHandler.sendMessage(mHandler.obtainMessage(CANCEL_HEAVY_NOTIFICATION_MSG,
5926 mHeavyWeightProcess.userId, 0));
5927 mHeavyWeightProcess = null;
5928
5929 boolean needRestart = false;
5930 if (app.pid > 0 && app.pid != MY_PID)
5931 int pid = app.pid;
5932 synchronized (mPidsSelfLocked)
5933 mPidsSelfLocked.remove(pid);
5934 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
5935
5936 mBatteryStatsService.noteProcessFinish(app.processName, app.info.uid);
5937 if (app.isolated)
5938 mBatteryStatsService.removeIsolatedUid(app.uid, app.info.uid);
5939
5940 boolean willRestart = false;
5941 if (app.persistent && !app.isolated)
5942 if (!callerWillRestart)
5943 willRestart = true;
5944 else
5945 needRestart = true;
5946
5947
前面的该通知的都通知到了,终于可以正式开杀了。
5948 app.kill(reason, true);
5949 handleAppDiedLocked(app, willRestart, allowRestart);
5950 if (willRestart)
5951 removeLruProcessLocked(app);
5952 addAppLocked(app.info, false, null /* ABI override */);
5953
5954 else
5955 mRemovedProcesses.add(app);
5956
5957
5958 return needRestart;
5959
ProcessRecord之kill
543 void kill(String reason, boolean noisy)
544 if (!killedByAm)
545 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "kill");
546 if (noisy)
547 Slog.i(TAG, "Killing " + toShortString() + " (adj " + setAdj + "): " + reason);
548
549 EventLog.writeEvent(EventLogTags.AM_KILL, userId, pid, processName, setAdj, reason);
550 Process.killProcessQuiet(pid);
551 Process.killProcessGroup(info.uid, pid);
552 if (!persistent)
553 killed = true;
554 killedByAm = true;
555
556 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
557
558
Process之killProcessQuiet
非常省事儿,发给一个SIGNAL_KILL出去就是了。
1068 public static final void killProcessQuiet(int pid)
1069 sendSignalQuiet(pid, SIGNAL_KILL);
1070
Process之killProcessGroup
这个直接用native写的。
public static final native int killProcessGroup(int uid, int pid);
android_util_Process.cpp之android_os_Process_killProcessGroup
JNI函数只是一个简单地对libprocessgroup中的killProcessGroup的封装
1035jint android_os_Process_killProcessGroup(JNIEnv* env, jobject clazz, jint uid, jint pid)
1036
1037 return killProcessGroup(uid, pid, SIGKILL);
1038
processgroup.cpp之killProcessGroup
这是我们的逻辑头一次走进/system/core/中,位于/system/core/libprocessgroup/processgroup.cpp
252int killProcessGroup(uid_t uid, int initialPid, int signal)
253
254 int processes;
255 const int sleep_us = 5 * 1000; // 5ms
256 int64_t startTime = android::uptimeMillis();
257 int retry = 40;
258
259 while ((processes = killProcessGroupOnce(uid, initialPid, signal)) > 0)
260 SLOGV("killed %d processes for processgroup %d\\n", processes, initialPid);
261 if (retry > 0)
262 usleep(sleep_us);
263 --retry;
264 else
265 SLOGE("failed to kill %d processes for processgroup %d\\n",
266 processes, initialPid);
267 break;
268
269
270
271 SLOGV("Killed process group uid %d pid %d in %" PRId64 "ms, %d procs remain", uid, initialPid,
272 android::uptimeMillis()-startTime, processes);
273
274 if (processes == 0)
275 return removeProcessGroup(uid, initialPid);
276 else
277 return -1;
278
279
killProcessGroupOnce
216static int killProcessGroupOnce(uid_t uid, int initialPid, int signal)
217
218 int processes = 0;
219 struct ctx ctx;
220 pid_t pid;
221
222 ctx.initialized = false;
223
224 while ((pid = getOneAppProcess(uid, initialPid, &ctx)) >= 0)
225 processes++;
226 if (pid == 0)
227 // Should never happen... but if it does, trying to kill this
228 // will boomerang right back and kill us! Let's not let that happen.
229 SLOGW("Yikes, we've been told to kill pid 0! How about we don't do that.");
230 continue;
231
232 if (pid != initialPid)
233 // We want to be noisy about killing processes so we can understand
234 // what is going on in the log; however, don't be noisy about the base
235 // process, since that it something we always kill, and we have already
236 // logged elsewhere about killing it.
237 SLOGI("Killing pid %d in uid %d as part of process group %d", pid, uid, initialPid);
238
239 int ret = kill(pid, signal);
240 if (ret == -1)
241 SLOGW("failed to kill pid %d: %s", pid, strerror(errno));
242
243
244
245 if (ctx.initialized)
246 close(ctx.fd);
247
248
249 return processes;
250
getOneAppProcess
我们再跟一下这个有趣的函数:getOneAppProcess
112static pid_t getOneAppProcess(uid_t uid, int appProcessPid, struct ctx *ctx)
113
114 if (!ctx->initialized)
115 int ret = initCtx(uid, appProcessPid, ctx);
116 if (ret < 0)
117 return ret;
118
119
120
121 char *eptr;
122 while ((eptr = (char *)memchr(ctx->buf_ptr, '\\n', ctx->buf_len)) == NULL)
123 int ret = refillBuffer(ctx);
124 if (ret == 0)
125 return -ERANGE;
126
127 if (ret < 0)
128 return ret;
129
130
131
132 *eptr = '\\0';
133 char *pid_eptr = NULL;
134 errno = 0;
135 long pid = strtol(ctx->buf_ptr, &pid_eptr, 10);
136 if (errno != 0)
137 return -errno;
138
139 if (pid_eptr != eptr)
140 return -EINVAL;
141
142
143 ctx->buf_len -= (eptr - ctx->buf_ptr) + 1;
144 ctx->buf_ptr = eptr + 1;
145
146 return (pid_t)pid;
147
removeProcessGroup
回头我们再看看removeProcessGroup,还要把对应的目录删掉。
149static int removeProcessGroup(uid_t uid, int pid)
150
151 int ret;
152 char path[PROCESSGROUP_MAX_PATH_LEN] = 0;
153
154 convertUidPidToPath(path, sizeof(path), uid, pid);
155 ret = rmdir(path);
156
157 convertUidToPath(path, sizeof(path), uid);
158 rmdir(path);
159
160 return ret;
161
AMS之removeProcessLocked(2)
5872 private final ProcessRecord removeProcessNameLocked(final String name, final int uid)
5873 ProcessRecord old = mProcessNames.remove(name, uid);
5874 if (old != null)
5875 old.uidRecord.numProcs--;
5876 if (old.uidRecord.numProcs == 0)
5877 // No more processes using this uid, tell clients it is gone.
5878 if (DEBUG_UID_OBSERVERS) Slog.i(TAG_UID_OBSERVERS,
5879 "No more processes in " + old.uidRecord);
5880 enqueueUidChangeLocked(old.uidRecord, true);
5881 mActiveUids.remove(uid);
5882
5883 old.uidRecord = null;
5884
5885 mIsolatedProcesses.remove(uid);
5886 return old;
5887
AMS之enqueueUidChangeLocked
18855 private final void enqueueUidChangeLocked(UidRecord uidRec, boolean gone)
18856 if (uidRec.pendingChange == null)
18857 if (mPendingUidChanges.size() == 0)
...
18860 mUiHandler.obtainMessage(DISPATCH_UIDS_CHANGED_MSG).sendToTarget();
18861
18862 final int NA = mAvailUidChanges.size();
18863 if (NA > 0)
18864 uidRec.pendingChange = mAvailUidChanges.remove(NA-1);
...
18867 else
18868 uidRec.pendingChange = new UidRecord.ChangeItem();
...
18871
18872 uidRec.pendingChange.uidRecord = uidRec;
18873 uidRec.pendingChange.uid = uidRec.uid;
18874 mPendingUidChanges.add(uidRec.pendingChange);
18875
18876 uidRec.pendingChange.gone = gone;
18877 uidRec.pendingChange.processState = uidRec.setProcState;
18878
DISPATCH_UIDS_CHANGED_MSG消息在Handler中是如何处理的呢?我们查AMS中的UiHandler:
1611 case DISPATCH_UIDS_CHANGED_MSG:
1612 dispatchUidsChanged();
1613 break;
AMS之dispatchUidsChanged
3787 private void dispatchUidsChanged()
3788 int N;
3789 synchronized (this)
3790 N = mPendingUidChanges.size();
3791 if (mActiveUidChanges.length < N)
3792 mActiveUidChanges = new UidRecord.ChangeItem[N];
3793
3794 for (int i=0; i<N; i++)
3795 final UidRecord.ChangeItem change = mPendingUidChanges.get(i);
3796 mActiveUidChanges[i] = change;
3797 change.uidRecord.pendingChange = null;
3798 change.uidRecord = null;
3799
3800 mPendingUidChanges.clear();
...
3803
3804
3805 if (mLocalPowerManager != null)
3806 for (int j=0; j<N; j++)
3807 UidRecord.ChangeItem item = mActiveUidChanges[j];
3808 if (item.gone)
3809 mLocalPowerManager.uidGone(item.uid);
3810 else
3811 mLocalPowerManager.updateUidProcState(item.uid, item.processState);
3812
3813
3814
3815
3816 int i = mUidObservers.beginBroadcast();
3817 while (i > 0)
3818 i--;
3819 final IUidObserver observer = mUidObservers.getBroadcastItem(i);
3820 if (observer != null)
3821 try
3822 for (int j=0; j<N; j++)
3823 UidRecord.ChangeItem item = mActiveUidChanges[j];
3824 if (item.gone)
...
3827 observer.onUidGone(item.uid);
3828 else
...
3832 observer.onUidStateChanged(item.uid, item.processState);
3833
3834
3835 catch (RemoteException e)
3836
3837
3838
3839 mUidObservers.finishBroadcast();
3840
3841 synchronized (this)
3842 for (int j=0; j<N; j++)
3843 mAvailUidChanges.add(mActiveUidChanges[j]);
3844
3845
3846
AMS之handleAppDiedLocked
最后我们再看一下handleAppDiedLocked,杀了之后,埋的事情也还是要管的。
4564 private final void handleAppDiedLocked(ProcessRecord app,
4565 boolean restarting, boolean allowRestart)
4566 int pid = app.pid;
后面大家可以看到这个清理用了180多行的代码,而这还不是全部。
4567 boolean kept = cleanUpApplicationRecordLocked(app, restarting, allowRestart, -1);
mLruProcesses也是要清理的。
4568 if (!kept && !restarting)
4569 removeLruProcessLocked(app);
4570 if (pid > 0)
4571 ProcessList.remove(pid);
4572
4573
4574
4575 if (mProfileProc == app)
4576 clearProfilerLocked();
4577
每个Activity负责去做自己的清理,这部分暂时先不分析了,以后用到了再说。
4579 // Remove this application's activities from active lists.
4580 boolean hasVisibleActivities = mStackSupervisor.handleAppDiedLocked(app);
4581
4582 app.activities.clear();
4583
4584 if (app.instrumentationClass != null)
4585 Slog.w(TAG, "Crash of app " + app.processName
4586 + " running instrumentation " + app.instrumentationClass);
4587 Bundle info = new Bundle();
4588 info.putString("shortMsg", "Process crashed.");
4589 finishInstrumentationLocked(app, Activity.RESULT_CANCELED, info);
4590
4591
4592 if (!restarting && hasVisibleActivities && !mStackSupervisor.resumeTopActivitiesLocked())
4593 // If there was nothing to resume, and we are not already
4594 // restarting this process, but there is a visible activity that
4595 // is hosted by the process... then make sure all visible
4596 // activities are running, taking care of restarting this
4597 // process.
4598 mStackSupervisor.ensureActivitiesVisibleLocked(null, 0);
4599
4600
AMS之removeLruProcessLocked
不光remove LRU,如果没杀掉的话,这里还会再杀一次。
2811 final void removeLruProcessLocked(ProcessRecord app)
2812 int lrui = mLruProcesses.lastIndexOf(app);
2813 if (lrui >= 0)
2814 if (!app.killed)
2815 Slog.wtfStack(TAG, "Removing process that hasn't been killed: " + app);
2816 Process.killProcessQuiet(app.pid);
2817 killProcessGroup(app.info.uid, app.pid);
2818
2819 if (lrui <= mLruProcessActivityStart)
2820 mLruProcessActivityStart--;
2821
2822 if (lrui <= mLruProcessServiceStart)
2823 mLruProcessServiceStart--;
2824
2825 mLruProcesses.remove(lrui);
2826
2827
AMS之cleanUpApplicationRecordLocked
这段就不细解释了,原文贴出来的原因是希望大家都体会到,埋葬还有这么多事情要做的。
15504 private final boolean cleanUpApplicationRecordLocked(ProcessRecord app,
15505 boolean restarting, boolean allowRestart, int index)
15506 if (index >= 0)
15507 removeLruProcessLocked(app);
15508 ProcessList.remove(app.pid);
15509
15510
15511 mProcessesToGc.remove(app);
15512 mPendingPssProcesses.remove(app);
15513
15514 // Dismiss any open dialogs.
15515 if (app.crashDialog != null && !app.forceCrashReport)
15516 app.crashDialog.dismiss();
15517 app.crashDialog = null;
15518
15519 if (app.anrDialog != null)
15520 app.anrDialog.dismiss();
15521 app.anrDialog = null;
15522
15523 if (app.waitDialog != null)
15524 app.waitDialog.dismiss();
15525 app.waitDialog = null;
15526
15527
15528 app.crashing = false;
15529 app.notResponding = false;
15530
15531 app.resetPackageList(mProcessStats);
15532 app.unlinkDeathRecipient();
15533 app.makeInactive(mProcessStats);
15534 app.waitingToKill = null;
15535 app.forcingToForeground = null;
15536 updateProcessForegroundLocked(app, false, false);
15537 app.foregroundActivities = false;
15538 app.hasShownUi = false;
15539 app.treatLikeActivity = false;
15540 app.hasAboveClient = false;
15541 app.hasClientActivities = false;
15542
15543 mServices.killServicesLocked(app, allowRestart);
15544
15545 boolean restart = false;
15546
15547 // Remove published content providers.
15548 for (int i = app.pubProviders.size() - 1; i >= 0; i--)
15549 ContentProviderRecord cpr = app.pubProviders.valueAt(i);
15550 final boolean always = app.bad || !allowRestart;
15551 boolean inLaunching = removeDyingProviderLocked(app, cpr, always);
15552 if ((inLaunching || always) && cpr.hasConnectionOrHandle())
15553 // We left the provider in the launching list, need to
15554 // restart it.
15555 restart = true;
15556
15557
15558 cpr.provider = null;
15559 cpr.proc = null;
15560
15561 app.pubProviders.clear();
15562
15563 // Take care of any launching providers waiting for this process.
15564 if (cleanupAppInLaunchingProvidersLocked(app, false))
15565 restart = true;
15566
15567
15568 // Unregister from connected content providers.
15569 if (!app.conProviders.isEmpty())
15570 for (int i = app.conProviders.size() - 1; i >= 0; i--)
15571 ContentProviderConnection conn = app.conProviders.get(i);
15572 conn.provider.connections.remove(conn);
15573 stopAssociationLocked(app.uid, app.processName, conn.provider.uid,
15574 conn.provider.name);
15575
15576 app.conProviders.clear();
15577
15578
15579 // At this point there may be remaining entries in mLaunchingProviders
15580 // where we were the only one waiting, so they are no longer of use.
15581 // Look for these and clean up if found.
15582 // XXX Commented out for now. Trying to figure out a way to reproduce
15583 // the actual situation to identify what is actually going on.
15584 if (false)
15585 for (int i = mLaunchingProviders.size() - 1; i >= 0; i--)
15586 ContentProviderRecord cpr = mLaunchingProviders.get(i);
15587 if (cpr.connections.size() <= 0 && !cpr.hasExternalProcessHandles())
15588 synchronized (cpr)
15589 cpr.launchingApp = null;
15590 cpr.notifyAll();
15591
15592
15593
15594
15595
15596 skipCurrentReceiverLocked(app);
15597
15598 // Unregister any receivers.
15599 for (int i = app.receivers.size() - 1; i >= 0; i--)
15600 removeReceiverLocked(app.receivers.valueAt(i));
15601
15602 app.receivers.clear();
15603
15604 // If the app is undergoing backup, tell the backup manager about it
15605 if (mBackupTarget != null && app.pid == mBackupTarget.app.pid)
15606 if (DEBUG_BACKUP || DEBUG_CLEANUP) Slog.d(TAG_CLEANUP, "App "
15607 + mBackupTarget.appInfo + " died during backup");
15608 try
15609 IBackupManager bm = IBackupManager.Stub.asInterface(
15610 ServiceManager.getService(Context.BACKUP_SERVICE));
15611 bm.agentDisconnected(app.info.packageName);
15612 catch (RemoteException e)
15613 // can't happen; backup manager is local
15614
15615
15616
15617 for (int i = mPendingProcessChanges.size() - 1; i >= 0; i--)
15618 ProcessChangeItem item = mPendingProcessChanges.get(i);
15619 if (item.pid == app.pid)
15620 mPendingProcessChanges.remove(i);
15621 mAvailProcessChanges.add(item);
15622
15623
15624 mUiHandler.obtainMessage(DISPATCH_PROCESS_DIED, app.pid, app.info.uid, Android 进程间通信的几种实现方式