用到的代码文件
frameworks/base/services/core/java/com/android/server/am/ProcessRecord.java
frameworks/base/core/java/android/os/Process.java
frameworks/base/core/jni/android_util_Process.cpp
system/core/libprocessgroup/processgroup.cpp
代码执行流程图
android process kill流程
下面的代码是以android N(api 24)为基础来进行流程分析。
在AMS(ActivityManagerService)中,进程的信息都保存在ProcessRecord数据结构中。如下这些都是AMS保存的进程信息。
//按照应用名称组织当前正在运行的进程
final ProcessMap<ProcessRecord> mProcessNames =
new ProcessMap<ProcessRecord>();
//当前正在运行的孤立进程
final SparseArray<ProcessRecord> mIsolatedProcesses =
new SparseArray<ProcessRecord>();
//按照pid组织当前正在运行的进程
final SparseArray<ProcessRecord> mPidsSelfLocked =
new SparseArray<ProcessRecord>();
//将要被移除的进程
final ArrayList<ProcessRecord> mRemovedProcesses =
new ArrayList<ProcessRecord>();
//进程死亡之后需要被gc的进程
final ArrayList<ProcessRecord> mProcessesToGc =
new ArrayList<ProcessRecord>();
ProcessRecord:包含着当前正在运行的指定一个进程的所有信息。也可以这么理解一个android中运行的应用程序对应着一个ProcessRecord。每一个进程当被kill的时候均会调用自身的kill()方法。
void kill(String reason, boolean noisy) {
if (!killedByAm) {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "kill");
if (noisy) {
Slog.i(TAG, "Killing " + toShortString()
+ " (adj " + setAdj + "): " + reason);
}
EventLog.writeEvent(EventLogTags.AM_KILL,
userId, pid, processName, setAdj, reason);
Process.killProcessQuiet(pid);
ActivityManagerService.killProcessGroup(uid, pid);
if (!persistent) {
killed = true;
killedByAm = true;
}
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
}
}
在kill()方法中调用“Process.killProcessQuiet(pid);”方法,而sendSignalQuiet是一个native方法。
/**
* @hide
* Private impl for avoiding a log message... DO NOT USE without doing
* your own log, or the Android Illuminati will find you some night and
* beat you up.
*/
public static final void killProcessQuiet(int pid) {
sendSignalQuiet(pid, SIGNAL_KILL);
}
/**
* @hide
* Private impl for avoiding a log message... DO NOT USE without doing
* your own log, or the Android Illuminati will find you some night and
* beat you up.
*/
public static final native void sendSignalQuiet(int pid, int signal);
下面是sendSignalQuiet这个native方法的具体实现。直接调用 signal.h 中的kill()方法杀掉进程。
void android_os_Process_sendSignalQuiet(JNIEnv* env,
jobject clazz, jint pid, jint sig)
{
if (pid > 0) {
kill(pid, sig);
}
}
在kill()方法中调用“Process.killProcessQuiet(pid);”方法后接着调用了“ActivityManagerService.killProcessGroup(uid, pid);”。
killProcessGroup()方法是声明在 ActivityManagerService 中的一个static方法。
static void killProcessGroup(int uid, int pid) {
if (sKillHandler != null) {
sKillHandler.sendMessage(
sKillHandler.obtainMessage(
KillHandler.KILL_PROCESS_GROUP_MSG, uid, pid));
} else {
Slog.w(TAG, "Asked to kill process group before system bringup!");
Process.killProcessGroup(uid, pid);
}
}
在KillHandler中handleMessage()方法的具体实现。
可以发现直接调用的是 Process.killProcessGroup() 这个static native方法。
public void handleMessage(Message msg) {
switch (msg.what) {
case KILL_PROCESS_GROUP_MSG:
{
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "killProcessGroup");
Process.killProcessGroup(msg.arg1 /* uid */, msg.arg2 /* pid */);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
}
break;
default:
super.handleMessage(msg);
}
}
/**
* 这个方法声明在Process.java文件中
* Kill all processes in a process group started for the given
* pid.
* @hide
*/
public static final native int killProcessGroup(int uid, int pid);
下面是killProcessGroup()这个native方法具体的执行流程:jni ->system/core/libprocessgroup。
在测试编译system/core这个so库时用mmma命令才编译成功。
这里有时候项目调节了log的输出级别,我开始用的V级别进行log输出,一直没有显示,后面改用E级别,log就成功输出来了。
jint android_os_Process_killProcessGroup(JNIEnv* env,
jobject clazz, jint uid, jint pid)
{
return killProcessGroup(uid, pid, SIGKILL);
}
static int killProcessGroupOnce(uid_t uid, int initialPid, int signal)
{
int processes = 0;
struct ctx ctx;
pid_t pid;
ctx.initialized = false;
while ((pid = getOneAppProcess(uid, initialPid, &ctx)) >= 0) {
processes++;
if (pid == 0) {
// Should never happen... but if it does, trying to kill
// this will boomerang right back and kill us! Let's not
// let that happen.
SLOGW( "Yikes, we've been told to kill pid 0!"
+" How about we don't do that.");
continue;
}
if (pid != initialPid) {
// We want to be noisy about killing processes so
// we can understand what is going on in the log;
// however, don't be noisy about the base
// process, since that it something we always kill,
// and we have already
// logged elsewhere about killing it.
SLOGI("Killing pid %d in uid %d as part"
+" of process group %d", pid, uid, initialPid);
}
int ret = kill(pid, signal);
if (ret == -1) {
SLOGW("failed to kill pid %d: %s", pid, strerror(errno));
}
}
if (ctx.initialized) {
close(ctx.fd);
}
return processes;
}
int killProcessGroup(uid_t uid, int initialPid, int signal)
{
SLOGE("method called killProcessGroup() kill signal"
+" %d processes for processgroup %d\n", signal, initialPid);
int processes;
const int sleep_us = 5 * 1000; // 5ms
int64_t startTime = android::uptimeMillis();
int retry = 40;
while ((processes =
killProcessGroupOnce(uid, initialPid, signal)) > 0) {
SLOGE("killed %d processes for processgroup %d\n",
processes, initialPid);
if (retry > 0) {
usleep(sleep_us);
--retry;
} else {
SLOGE("failed to kill %d processes for processgroup %d\n",
processes, initialPid);
break;
}
}
SLOGE("Killed process group uid %d pid %d in %" PRId64 "ms,
%d procs remain", uid, initialPid,
android::uptimeMillis()-startTime, processes);
if (processes == 0) {
return removeProcessGroup(uid, initialPid);
} else {
return -1;
}
}
static int removeProcessGroup(uid_t uid, int pid)
{
int ret;
char path[PROCESSGROUP_MAX_PATH_LEN] = {0};
convertUidPidToPath(path, sizeof(path), uid, pid);
ret = rmdir(path);
SLOGE("removeProcessGroup convertUidPidToPath %s\n", path);
convertUidToPath(path, sizeof(path), uid);
rmdir(path);
SLOGE("removeProcessGroup convertUidToPath %s\n", path);
return ret;
}
下面是libprocessgroup.so中我添加的一些log输出,可以看见主要是停止相关进程并清除相关进程文件。
/*
* 这里的信号级别kill signal 9我认为跟linux的信号级别是一致的,
*我们一般在linux中杀掉某个进程一般都采用的是kill -9 pid
*/
system_process E/libprocessgroup:
method called killProcessGroup() kill signal 9 processes
for processgroup 3837
system_process E/libprocessgroup:
Killed process group uid 10064 pid 3837 in 112ms,
0 procs remain
system_process E/libprocessgroup:
removeProcessGroup convertUidPidToPath
/acct/uid_10064/pid_3837
system_process E/libprocessgroup:
removeProcessGroup convertUidToPath
/acct/uid_10064
本文由 tuzhao 创作,采用 知识共享署名4.0 国际许可协议进行许可
本站文章除注明转载/出处外,均为本站原创或翻译,转载前请务必署名
最后编辑时间为:
2017/11/23 09:54