Android源码分析--system_server进程分析

在上一篇博文中我们进行了有关Zygote进程的分析,我们知道Zygote进程创建了一个重要的进程–system_server进程后就进入了无限循环中,之后Android系统中的重要任务就交给了system_server进程,作为zygote的嫡长子进程,system_server进程的意义非凡,今天我们来分析一下system_server进程。

创建system_server进程

在ZygoteInit中main方法中,通过调用startSystemServer方法开启了system_server进程。该方法主要为创建system_server进程准备了一些参数,并调用本地方法forkSystemServer创建system_server进程。让我们来看一下startSystemServer方法的代码:

    private static boolean startSystemServer()
            throws MethodAndArgsCaller, RuntimeException {

        String args[] = {
            "--setuid=1000",
            "--setgid=1000",
            "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1032,3001,3002,3003,3006,3007",
            "--capabilities=130104352,130104352",
            "--runtime-init",
            "--nice-name=system_server",
            "com.android.server.SystemServer",
        };
        ZygoteConnection.Arguments parsedArgs = null;

        int pid;

        try {
            parsedArgs = new ZygoteConnection.Arguments(args);
            ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);
            ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs);

            /* 创建system_server进程 */
            pid = Zygote.forkSystemServer(
                    parsedArgs.uid, parsedArgs.gid,
                    parsedArgs.gids,
                    parsedArgs.debugFlags,
                    null,
                    parsedArgs.permittedCapabilities,
                    parsedArgs.effectiveCapabilities);
        } catch (IllegalArgumentException ex) {
            throw new RuntimeException(ex);
        }

        /* 子进程中执行 */
        if (pid == 0) {
            handleSystemServerProcess(parsedArgs);
        }

        return true;
    }

这里的代码并不复杂,可以看到,他调用了forkSystemServer方法来创建一个新的进程,之后在子进程,即system_server进程中执行handleSystemServerProcess方法。下面我们来看一下forkSystemServer方法,它是一个native方法对应的源文件在dalvik\vm\native\dalvik_system_Zygote.cpp中。代码如下:

static void Dalvik_dalvik_system_Zygote_forkSystemServer(
        const u4* args, JValue* pResult)
{
    pid_t pid;
    pid = forkAndSpecializeCommon(args, true);

    /* zygote进程检查其子进程是否死掉 */
    if (pid > 0) {
        int status;

        ALOGI("System server process %d has been created", pid);
        gDvm.systemServerPid = pid;
        /*  如果system_server进程退出,则zygote进程也会被杀掉 */
        if (waitpid(pid, &status, WNOHANG) == pid) {
            ALOGE("System server process %d has died. Restarting Zygote!", pid);
            kill(getpid(), SIGKILL);
        }
    }
    RETURN_INT(pid);
}

从代码中可以看到在forkAndSpecializeCommon方法中,我们创建了子进程,并返回了子进程id,接下来我检查如果system_server进程是否退出,若是的话则zygote进程也将会被被干掉,由此可见其重要性。接下来我们来看forkAndSpecializeCommon的代码,这个system_server进程的创建真的是千峰百转啊。。。

static pid_t forkAndSpecializeCommon(const u4* args, bool isSystemServer)
{
    pid_t pid;

    uid_t uid = (uid_t) args[0];
    gid_t gid = (gid_t) args[1];
    ArrayObject* gids = (ArrayObject *)args[2];
    u4 debugFlags = args[3];
    ArrayObject *rlimits = (ArrayObject *)args[4];
    u4 mountMode = MOUNT_EXTERNAL_NONE;
    int64_t permittedCapabilities, effectiveCapabilities;
    char *seInfo = NULL;
    char *niceName = NULL;
    //传入参数isSystemServer为true
    if (isSystemServer) {
        permittedCapabilities = args[5] | (int64_t) args[6] << 32;
        effectiveCapabilities = args[7] | (int64_t) args[8] << 32;
    } else {
       ......
    }

    if (!gDvm.zygote) {
        dvmThrowIllegalStateException(
            "VM instance not started with -Xzygote");

        return -1;
    }
    // 在第一次调用fork函数之前需要调用
    if (!dvmGcPreZygoteFork()) {
        ALOGE("pre-fork heap failed");
        dvmAbort();
    }
    setSignalHandler();
    //向log文件中写入一些数据
    dvmDumpLoaderStats("zygote");
    //子进程被fork出来
    pid = fork();
    if (pid == 0) {
    //在这里根据传入的参数对子进程做出一些处理,例如设置进程名,设置各种id等
    ......
    }

    return pid;
}

至此system_server进程终于被创建出来,我们可以看到system_server进程也是通过Linux系统特有的Fork机制分裂克隆出来的。在fork之前,我们还有一个重要方法没有分析–setSignalHandler方法,该方法用来设置信号处理,下面让我来看一下吧。

static void setSignalHandler()
{
    int err;
    struct sigaction sa;

    memset(&sa, 0, sizeof(sa));

    sa.sa_handler = sigchldHandler;

    err = sigaction (SIGCHLD, &sa, NULL);//设置信号处理函数,该信号是子进程死亡的信号

    if (err < 0) {
        ALOGW("Error setting SIGCHLD handler: %s", strerror(errno));
    }
}
static void sigchldHandler(int s)
{
    pid_t pid;
    int status;

    while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
        /* 打印出我们所关心的进程的死亡状态. */
        ......

        /*
         * 如果刚刚销毁的进程是system_server, 同时杀死zygote进程
         * 这样system_server进程和zygote进程将会被init进程重启
         */
        if (pid == gDvm.systemServerPid) {
            ALOG(LOG_INFO, ZYGOTE_LOG_TAG,
                "Exit zygote because system server (%d) has terminated",
                (int) pid);
            kill(getpid(), SIGKILL);
        }
    }

    if (pid < 0) {
        ALOG(LOG_WARN, ZYGOTE_LOG_TAG,
            "Zygote SIGCHLD error in waitpid: %s",strerror(errno));
    }
}

这里我们发现我们之前已经看到在forkSystemServer方法中已经检查过system_server进程是否死亡,为什么这里还要再一次进行检查?这是为了防止在我们还没有得到fork子进程的pid时,system_server进程就已经死亡的情况。

总结一下:system_server进程的创建经历了漫长的历程:首先startSystemServer中调用了native方法forkSystemServer;之后在native方法forkSystemServer中调用了forkAndSpecializeCommon方法;在forkAndSpecializeCommon方法中fork之前还调用了setSignalHandler来设置信号处理项。这样,我们的system_server进程终于被创建起来,同时他还和zygote进程保持着同生共死的关系。

system_server进程的职责

在startSystemServer的方法中我们可以看到,在创建进程之后,在子进程即system_server进程中会执行handleSystemServerProcess方法,这便是system_server的职责所在,下面我们来看一下:

    private static void handleSystemServerProcess(
            ZygoteConnection.Arguments parsedArgs)
            throws ZygoteInit.MethodAndArgsCaller {

        closeServerSocket();
        // 设置权限.
        Libcore.os.umask(S_IRWXG | S_IRWXO);
        ......
        if (parsedArgs.invokeWith != null) {
        ......
        } else {
            /* 剩余的参数传递到SystemServer. */
            RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs);
        }
    }

可以看到最后system_server进程来到了RuntimeInit中,它的实现在frameworks\base\core\java\com\android\internal\os\RuntimeInit.java中

    public static final void zygoteInit(int targetSdkVersion, String[] argv)
            throws ZygoteInit.MethodAndArgsCaller {
        if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting application from zygote");

        //关闭System.out和System.err,使用Android log
        redirectLogStreams();
        //做一些常规初始化
        commonInit();
        //native层初始化,调用此方法之后system_server将与Binder通信系统建立联系,这样就可以使用Binder了
        nativeZygoteInit();

        applicationInit(targetSdkVersion, argv);
    }
    private static void applicationInit(int targetSdkVersion, String[] argv)
            throws ZygoteInit.MethodAndArgsCaller {
        ......
        try {
            args = new Arguments(argv);
        } catch (IllegalArgumentException ex) {
            Slog.e(TAG, ex.getMessage());
            // let the process exit
            return;
        }
        invokeStaticMain(args.startClass, args.startArgs);
    }

可以看到,最终我们调用了invokeStaticMain方法,该方法的传入参数在startSystemServer方法中被设置,其传入参数的类名是”com.android.server.SystemServer”

    private static void invokeStaticMain(String className, String[] argv)
            throws ZygoteInit.MethodAndArgsCaller {
        Class<?> cl;

        try {
            cl = Class.forName(className);
        } catch (ClassNotFoundException ex) {
            throw new RuntimeException(
                    "Missing class when invoking static main " + className,
                    ex);
        }

        Method m;
        try {
            m = cl.getMethod("main", new Class[] { String[].class });
        } catch (NoSuchMethodException ex) {
            throw new RuntimeException(
                    "Missing static main on " + className, ex);
        } catch (SecurityException ex) {
            throw new RuntimeException(
                    "Problem getting static main on " + className, ex);
        }

        int modifiers = m.getModifiers();
        if (! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) {
            throw new RuntimeException(
                    "Main method is not public and static on " + className);
        }

        /* 抛出的异常在ZygoteInit.main()中被截获 */
        throw new ZygoteInit.MethodAndArgsCaller(m, argv);
    }

让我们来看看被截获的语句:

 catch (MethodAndArgsCaller caller) {
            caller.run();//调用了caller的run方法
        } 

run方法代码:

public void run() {
            try {
                mMethod.invoke(null, new Object[] { mArgs });
            } catch (IllegalAccessException ex) {
                throw new RuntimeException(ex);
            } catch (InvocationTargetException ex) {
                Throwable cause = ex.getCause();
                if (cause instanceof RuntimeException) {
                    throw (RuntimeException) cause;
                } else if (cause instanceof Error) {
                    throw (Error) cause;
                }
                throw new RuntimeException(ex);
            }
        }

可以看到,在函数最后抛出异常,在ZygoteInit.main()中被截获,由于传递的参数类名是”com.android.server.SystemServer”,这样我们调用了MethodAndArgsCaller.run()方法去执行了SystemServer类的静态main方法。(关于ZygoteInit可以参考上一篇博文:Android源码分析–Zygote进程分析

    public static void main(String[] args) {
        ......
        // Mmmmmm... more memory!
        dalvik.system.VMRuntime.getRuntime().clearGrowthLimit();

        // system server一直在运行, 所以他需要尽可能有效的利用内存
        VMRuntime.getRuntime().setTargetHeapUtilization(0.8f);

        Environment.setUserRequired(true);

        System.loadLibrary("android_servers");

        Slog.i(TAG, "Entered the Android system server!");

        // native方法,进行一些传感器服务的初始化
        nativeInit();

        // 创建一个单独的线程,在这里启动系统的各项服务
        ServerThread thr = new ServerThread();
        thr.initAndLoop();
    }

最终,system_server开启了一个新的线程,并执行了它的initAndLoop方法,其也被定义在SystemServer.java中,该方法的代码较多,其主要的工作就是开启了系统中的各项服务,如电池服务,蓝牙服务等等。并调用了Looper的prepareMainLooper方法进行消息循环,然后处理消息,这里不再赘述。

最后,我们来总结一下:

  • 首先system_server执行handleSystemServerProcess方法来完成自己的使命;
  • 之后调用RuntimeInit.zygoteInit方法,在这里我们进行了一些常规的初始化工作已经native层的初始化,从而与Binder通信建立联系;
  • 之后调用invokeStaticMain方法,利用抛出异常的方法在ZygoteInit的main方法中截获并去执行SystemServer的main方法;
  • 在SystemServer的main方法中,我调用nativeInit方法去初始化一些传感器服务,并开启了单独的线程去开启Android系统中的各项服务,并调用了Looper的prepareMainLooper方法进行消息循环,然后处理消息
时间: 2024-10-19 09:24:56

Android源码分析--system_server进程分析的相关文章

Android源码分析:Telephony部分–phone进程

Android源码分析:Telephony部分–phone进程红狼博客 com.android.phone进程 它就象个后台进程一样,开机即运行并一直存在.它的代码位于:packages/apps/Phone/src/com/android/phone 当有来电时,它会作出反应,如显示UI和铃声提示:当在通话过程中,它显示InCallScreen: 当要拨号时ITeleohony的接口调用最终到Phone进程,然后由它去与PhoneFactory创建的GSMPhone或CDMAPhone进行交互

Android 源码分析工具

标 题: [原创]Android源码分析工具及方法作 者: MindMac时 间: 2014-01-02,09:32:35链 接: http://bbs.pediy.com/showthread.php?t=183278 在对 Android 源码进行分析时,如果有得力的工具辅助,会达到事半功倍的效果.本文介绍了一些在分析 Android 源码时使用的一些工具和方法,希望能够帮助到有需要的同学. Eclipse 在 Android 应用程序开发过程中,一般会使用 Eclipse,当然 Googl

Android源码分析:Telephony部分–GSMPhone

Android源码分析:Telephony部分–GSMPhone红狼博客 PhoneProxy/GSMPhone/CDMAPhone 如果说RILJ提供了工具或管道,那么Phone接口的子类及PhoneFactory则为packages/app/Phone这个应用程序进程使用RILJ这个工具或管道提供了极大的方便,它们一个管理整个整个手机的Telephony功能. GSMPhone和CDMAPhone实现了Phone中定义的接口.接口类Phone定义了一套API,这套API用于使用RILJ(见后

Android源码分析之SharedPreferences

在Android的日常开发中,相信大家都用过SharedPreferences来保存用户的某些settings值.Shared Preferences 以键值对的形式存储私有的原生类型数据,这里的私有的是指只对你自己的app可见的,也就是说别的app是无法访问到的. 客户端代码为了使用它有2种方式,一种是通过Context#getSharedPreferences(String prefName, int mode)方法, 另一种是Activity自己的getPreferences(int mo

Android源码分析--MediaServer源码分析(二)

在上一篇博客中Android源码分析–MediaServer源码分析(一),我们知道了ProcessState和defaultServiceManager,在分析源码的过程中,我们被Android的Binder通信机制中的各种复杂的类关系搞的眼花缭乱,接下来我们就以MediaPlayerService为例来分析一下Binder的通信机制.首先来回顾一下: BpBinder和BBinder都是Android中Binder通信的代表类,其中BpBinder是客户端用来与Server交互的代理类,p代

Cordova Android源码分析系列一(项目总览和CordovaActivity分析)

PhoneGap/Cordova是一个专业的移动应用开发框架,是一个全面的WEB APP开发的框架,提供了以WEB形式来访问终端设备的API的功能.这对于采用WEB APP进行开发者来说是个福音,这可以避免了原生开发的某些功能.Cordova 只是个原生外壳,app的内核是一个完整的webapp,需要调用的原生功能将以原生插件的形式实现,以暴露js接口的方式调用. Cordova Android项目是Cordova Android原生部分的Java代码实现,提供了Android原生代码和上层We

Android源码分析之SparseArray

本来接下来应该分析MessageQueue了,可是我这几天正好在实际开发中又再次用到了SparseArray(之前有用到过一次,那次只是 大概浏览了下源码,没做深入研究),于是在兴趣的推动下,花了些时间深入研究了下,趁着记忆还是新鲜的,就先在这里分析了. MessageQueue的分析应该会在本周末给出. 和以往一样,首先我们来看看关键字段和ctor: private static final Object DELETED = new Object(); private boolean mGar

如何高效地分析Android_log中的问题?——查看Android源码

在日常解bugs时,需要通过log日志来分析问题,例如查看crash发生时的堆栈信息时,就会有Android的源码的调用,这是就要去查看Android源码. 1.进入Android源码网址查看,例如 http://androidxref.com/ 2.选择对应的Android版本,例如Android 4.4 3.选择framework,在File Path中输入类名,点击Search,选择对应的类名. 4.查看Android源码!

Android源码分析之Builder模式

http://www.w3c.com.cn/android%E6%BA%90%E7%A0%81%E5%88%86%E6%9E%90%E4%B9%8Bbuilder%E6%A8%A1%E5%BC%8F Android源码分析之Builder模式