android进程kill流程分析

/ android / 没有评论 / 1984浏览

用到的代码文件

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 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