关于Android的浅杀
android.app.ActivityManager类提供了removeTask方法来清理任务。
在API21及之前,removeTask中提供一个参数来指定是否要连同任务所运行的进程一起杀掉。
这个方法的第二个参数就是用来指定是否要连同进程一起杀掉,可以为0或者REMOVE_TASK_KILL_PROCESS。
我们先看在4.4上的实现:
/** * Completely remove the given task. * * @param taskId Identifier of the task to be removed. * @param flags Additional operational flags. May be 0 or * {@link #REMOVE_TASK_KILL_PROCESS}. * @return Returns true if the given task was found and removed. * * @hide */ public boolean removeTask(int taskId, int flags) throws SecurityException { try { return ActivityManagerNative.getDefault().removeTask(taskId, flags); } catch (RemoteException e) { // System dead, we will be dead too soon! return false; } }
在ActivityManager中提供的只是一个接口,真正的实现要通过IPC去调用ActivityManagerService的removeTask. 主要的逻辑在cleanUpRemovedTaskLocked中实现。
@Override public boolean removeTask(int taskId, int flags) {... try { TaskRecord tr = recentTaskForIdLocked(taskId); if (tr != null) { ActivityRecord r = tr.removeTaskActivitiesLocked(-1, false); if (r != null) { cleanUpRemovedTaskLocked(tr, flags); return true; }... }
我们再往下看cleanUpRemovedTaskLocked的逻辑,如果flags&ActivityManager.REMOVE_TASK_KILL_PROCESS就杀进程。
private void cleanUpRemovedTaskLocked(TaskRecord tr, int flags) {... final boolean killProcesses = (flags&ActivityManager.REMOVE_TASK_KILL_PROCESS) != 0;... if (killProcesses) {... killUnneededProcessLocked(pr, "remove task"); } else { pr.waitingToKill = "remove task"; } } } }
杀进程的逻辑在killUnneededProcessLocked中,接着调用android.os.Process.killProcessQuiet方法来杀进程。然后调用bionic中的函数来做系统调用。
private void killUnneededProcessLocked(ProcessRecord pr, String reason) { if (!pr.killedByAm) { Slog.i(TAG, "Killing " + pr.toShortString() + " (adj " + pr.setAdj + "): " + reason); EventLog.writeEvent(EventLogTags.AM_KILL, pr.userId, pr.pid, pr.processName, pr.setAdj, reason); pr.killedByAm = true; Process.killProcessQuiet(pr.pid); } }
比如ARM的kill调用是这样的:
ENTRY(kill) mov ip, r7 ldr r7, =__NR_kill swi #0 mov r7, ip cmn r0, #(MAX_ERRNO + 1) bxls lr neg r0, r0 b __set_errno_internalEND(kill)
在AArch64状态下,swi已经失效了,替换成svc指令。
ENTRY(kill) mov x8, __NR_kill svc #0 cmn x0, #(MAX_ERRNO + 1) cneg x0, x0, hi b.hi __set_errno_internal retEND(kill)
在Intel x86芯片上,系统调用要用int 0x80软中断。
ENTRY(kill) pushl %ebx pushl %ecx mov 12(%esp), %ebx mov 16(%esp), %ecx movl $__NR_kill, %eax int $0x80 cmpl $-MAX_ERRNO, %eax jb 1f negl %eax pushl %eax call __set_errno addl $4, %esp orl $-1, %eax1: popl %ecx popl %ebx retEND(kill)
但是在x86_64指令集中,系统调用已经变成基本指令了,不再需要int 0x80了。
ENTRY(kill) movl $__NR_kill, %eax syscall cmpq $-MAX_ERRNO, %rax jb 1f negl %eax movl %eax, %edi call __set_errno_internal1: retEND(kill)
从API 22开始,情况出现了一些变化,带参数的API被取消了,默认就杀进程。
我们看5.1的代码:
/** * Completely remove the given task. * * @param taskId Identifier of the task to be removed. * @return Returns true if the given task was found and removed. * * @hide */ public boolean removeTask(int taskId) throws SecurityException { try { return ActivityManagerNative.getDefault().removeTask(taskId); } catch (RemoteException e) { // System dead, we will be dead too soon! return false; } }
经过IPC,走到ActivityManagerService中,默认调用removeTaskByIdLocked时就杀进程。
@Override public boolean removeTask(int taskId) { synchronized (this) { enforceCallingPermission(android.Manifest.permission.REMOVE_TASKS, "removeTask()"); long ident = Binder.clearCallingIdentity(); try { return removeTaskByIdLocked(taskId, true); } finally { Binder.restoreCallingIdentity(ident); } } }
我们继续看removeTaskByIdLocked,还是会调用cleanUpRemovedTaskLocked,这两个方法都是可以控制是否要杀进程的。
/** * Removes the task with the specified task id. * * @param taskId Identifier of the task to be removed. * @param killProcess Kill any process associated with the task if possible. * @return Returns true if the given task was found and removed. */ private boolean removeTaskByIdLocked(int taskId, boolean killProcess) { TaskRecord tr = mStackSupervisor.anyTaskForIdLocked(taskId); if (tr != null) { tr.removeTaskActivitiesLocked(); cleanUpRemovedTaskLocked(tr, killProcess); if (tr.isPersistable) { notifyTaskPersisterLocked(null, true); } return true; } Slog.w(TAG, "Request to remove task ignored for non-existent task " + taskId); return false; }
private void cleanUpRemovedTaskLocked(TaskRecord tr, boolean killProcess) { mRecentTasks.remove(tr); tr.removedFromRecents();...... if (!killProcess) { return; }......
更多相关文章
- android 6.0 以上 动态申请多个权限
- Android短彩信收发流程(应用层)
- 使用traceview进行Android性能测试
- Android使用Fragment来实现ViewPager的功能(解决切换Fragment状态
- SecureRandom漏洞解析
- Android(安卓)中application 详解
- android Binder Linux IPC 内核 驱动
- Android(安卓)3.2 以上转屏,切换屏幕,横竖屏(onConfigurationChange
- Android学习笔记50:使用WebView控件浏览网页