关于Android的浅杀
2016-01-28 21:01
375 查看
android.app.ActivityManager类提供了removeTask方法来清理任务。
在API21及之前,removeTask中提供一个参数来指定是否要连同任务所运行的进程一起杀掉。
这个方法的第二个参数就是用来指定是否要连同进程一起杀掉,可以为0或者REMOVE_TASK_KILL_PROCESS。
我们先看在4.4上的实现:
在ActivityManager中提供的只是一个接口,真正的实现要通过IPC去调用ActivityManagerService的removeTask. 主要的逻辑在cleanUpRemovedTaskLocked中实现。
我们再往下看cleanUpRemovedTaskLocked的逻辑,如果flags&ActivityManager.REMOVE_TASK_KILL_PROCESS就杀进程。
杀进程的逻辑在killUnneededProcessLocked中,接着调用android.os.Process.killProcessQuiet方法来杀进程。然后调用bionic中的函数来做系统调用。
比如ARM的kill调用是这样的:
在AArch64状态下,swi已经失效了,替换成svc指令。
在Intel x86芯片上,系统调用要用int 0x80软中断。
但是在x86_64指令集中,系统调用已经变成基本指令了,不再需要int 0x80了。
从API 22开始,情况出现了一些变化,带参数的API被取消了,默认就杀进程。
我们看5.1的代码:
经过IPC,走到ActivityManagerService中,默认调用removeTaskByIdLocked时就杀进程。
我们继续看removeTaskByIdLocked,还是会调用cleanUpRemovedTaskLocked,这两个方法都是可以控制是否要杀进程的。
在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_internal END(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 ret END(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, %eax 1: popl %ecx popl %ebx ret END(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_internal 1: ret END(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 实现漫天飞舞雪花以及下雨天的效果
- android 导航栏透明
- Android 基础 —— 模拟实现拨打电话功能
- android之浮动title
- Android中自定义一个事件监听器
- Android自定义View
- Android中Relativelayout各个属性
- Android 6.0 inflate过程分析
- Android 5.1编译
- 【第一行代码】Android日志工具
- Android实现边录音边播放
- 【第一行代码】Android项目目录结构
- Android 四大组件 —— 活动(活动的隐式跳转)
- appium+java+cucumber+selenium-webdriver android
- android TextView实现跑马灯效果
- Android学习-----Android Studio 2.0 预览版下载
- 【免翻墙】搭建Android开发环境
- 【Android开发新手的学习笔记】使用LruCache对ListView进行优化
- Android Scroller完全解析,关于Scroller你所需知道的一切
- Android AsyncTask软件升级