码迷,mamicode.com
首页 > 其他好文 > 详细

SystemServer分析

时间:2014-05-26 13:37:58      阅读:375      评论:0      收藏:0      [点我收藏+]

标签:android   c   class   code   java   tar   

1 SystemServer分析

SystemServer的进程名就是前面所说的“system_server”,是zygote进程“app_process”fork出来的第一个子嗣,其重要性不言而喻。下面我们简称其为SS。

1.1  SS的诞生

先回顾一下SS是如何创建的:

/*在zygoteinit.java的startsystemserver方法中*/

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=" + capabilities + "," + capabilities,

            "--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);

            /* Request to fork the system server process */

            pid = Zygote.forkSystemServer( //调用此函数创建SS

                    parsedArgs.uid, parsedArgs.gid,

                    parsedArgs.gids,

                    parsedArgs.debugFlags,

                    null,

                    parsedArgs.permittedCapabilities,

                    parsedArgs.effectiveCapabilities);

        } catch (IllegalArgumentException ex) {

            throw new RuntimeException(ex);

        }

 

下面看看forkSystemServer函数的具体内容 :

/*在Dalvik_dalvik_system_Zygote.cpp中)*/

 

/*

 * native public static int nativeForkSystemServer(int uid, int gid,

 *     int[] gids, int debugFlags, int[][] rlimits,

 *     long permittedCapabilities, long effectiveCapabilities);

 */

static void Dalvik_dalvik_system_Zygote_forkSystemServer(

        const u4* args, JValue* pResult)

{

pid_t pid;

/*根据参数fork一个子进程SS,并返回子进程的PID*/

    pid = forkAndSpecializeCommon(args, true, true);

    /* The zygote process checks whether the child process has died or not. */

    if (pid > 0) {

        int status;

        ALOGI("System server process %d has been created", pid);

        gDvm.systemServerPid = pid; //保存SS的PID

        /* There is a slight window that the system server process has crashed

         * but it went unnoticed because we haven‘t published its pid yet. So

         * we recheck here just to make sure that all is well.

         */

    /*函数退出前需要先检查创建的子进程SS是否退出了*/

        if (waitpid(pid, &status, WNOHANG) == pid) {

//如果SS退出了,那么zygote就自杀~

            ALOGE("System server process %d has died. Restarting Zygote!", pid);

            kill(getpid(), SIGKILL);

        }

    }

    RETURN_INT(pid);

}

下面在看看forkAndSpecializeCommon函数主要完成两个工作:1,根据传入的参数对子进程做一些处理,如设置进程名,各种id等;2,就是调用很重要的信号处理函数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));

    }

}

 

/*再看sigchldHandler函数,此函数由zygote在fork子进程之前调用!*/

 

static void sigchldHandler(int s)

{

    pid_t pid;

    int status;

    while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {

        /* LOG死亡子进程的状态,以便调试*/

        if (WIFEXITED(status)) {

            if (WEXITSTATUS(status)) {

                ALOG(LOG_DEBUG, ZYGOTE_LOG_TAG, "Process %d exited cleanly (%d)",

                    (int) pid, WEXITSTATUS(status));

            } else {

                IF_ALOGV(/*should use ZYGOTE_LOG_TAG*/) {

                    ALOG(LOG_VERBOSE, ZYGOTE_LOG_TAG,

                        "Process %d exited cleanly (%d)",

                        (int) pid, WEXITSTATUS(status));

                }

            }

        } else if (WIFSIGNALED(status)) {

            if (WTERMSIG(status) != SIGKILL) {

                ALOG(LOG_DEBUG, ZYGOTE_LOG_TAG,

                    "Process %d terminated by signal (%d)",

                    (int) pid, WTERMSIG(status));

            } else {

                IF_ALOGV(/*should use ZYGOTE_LOG_TAG*/) {

                    ALOG(LOG_VERBOSE, ZYGOTE_LOG_TAG,

                        "Process %d terminated by signal (%d)",

                        (int) pid, WTERMSIG(status));

                }

            }

#ifdef WCOREDUMP

            if (WCOREDUMP(status)) {

                ALOG(LOG_INFO, ZYGOTE_LOG_TAG, "Process %d dumped core",

                    (int) pid);

            }

#endif /* ifdef WCOREDUMP */

        }

/*如果崩溃的子进程是SS,那么zygote就自杀,然后由init进程重新fork zygote进程,进而重启SS进程*/

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

}

}

 

从上面的分析可以看出SS同zygote进程同生共死,可见SS的重要性!下面开始分析SS在Android系统中到底扮演者什么样的角色。

1.2  SS的使命

SS进程诞生后,就同zygote进程分道扬镳了。它有了自己的使命,那么它的使命是什么呢?这需要我们会到zygotinit.java文件中的startSystemServer方法中:

try {

……

            pid = Zygote.forkSystemServer(…);

        } catch (IllegalArgumentException ex) {

            throw new RuntimeException(ex);

        }

        /* For child process */

        if (pid == 0) {

//这里就是SS的使命

            handleSystemServerProcess(parsedArgs);

        }

 

/* handleSystemServerProcess 的详细代码如下*/

private static void handleSystemServerProcess(

            ZygoteConnection.Arguments parsedArgs)

            throws ZygoteInit.MethodAndArgsCaller {

        closeServerSocket(); //首先关闭从zygote继承来的socket

   //然后将umask值设为0077,这样的话新创建的文件和目录在默认情况下就//只有创建用户本身拥有读写权限了~

        Libcore.os.umask(S_IRWXG | S_IRWXO);

        if (parsedArgs.niceName != null) {

            Process.setArgV0(parsedArgs.niceName); //有昵称就设置昵称

        }

        if (parsedArgs.invokeWith != null) {

            WrapperInit.execApplication(parsedArgs.invokeWith,

                    parsedArgs.niceName, parsedArgs.targetSdkVersion,

                    null, parsedArgs.remainingArgs);

        } else {

           

 /*调用zygoteInit函数,并将主要的参数传递给SS*/

            RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs);

        }

    }

现在SS就进入到RuntimeInit类中了,zygoteInit的代码在RuntimeInit.java中,详细代码如下:

/**

     * The main function called when started through the zygote process. This

     * could be unified with main(), if the native code in nativeFinishInit()

     * were rationalized with Zygote startup.<p>

     *

     * Current recognized args:

     * <ul>

     *   <li> <code> [--] &lt;start class name&gt;  &lt;args&gt;

     * </ul>

     *

     * @param targetSdkVersion target SDK version

     * @param argv arg strings

     */

    public static final void zygoteInit(int targetSdkVersion, String[] argv)

            throws ZygoteInit.MethodAndArgsCaller {

        if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting application from zygote");

/*Redirect System.out and System.err to the Android log.分别对应log.info和log.warm*/

        redirectLogStreams();

/*做一些常规初始化操作:很简单,可以看源代码中的注释*/

        commonInit();

/*key1 native层的初始化*/

        nativeZygoteInit();

/*key2 应用层的初始化,其实主要是通过调用invokeStaticMain函数来调用com.android.server.SystemServer类的main函数*/

        applicationInit(targetSdkVersion, argv);

    }

下面开始详细分析key1和key2。

1、nativeZygoteInit分析

nativeZygoteInit是一个native函数,它的实现在androidRuntime.cpp中

static void com_android_internal_os_RuntimeInit_nativeZygoteInit(JNIEnv* env, jobject clazz)

{

    gCurRuntime->onZygoteInit();

}

gCurRuntime 是什么呢?回顾app_process(zygote)的main函数中有:

AppRuntime runtime;

AppRuntime类的定义:

class AppRuntime : public AndroidRuntime // AppRuntime继承于AndroidRuntime

 

而gCurRuntime定义如下:

static AndroidRuntime* gCurRuntime = NULL;  

//说明 gCurRuntime是一个AndroidRuntime类对象

 

AndroidRuntime的构造函数如下:

AndroidRuntime::AndroidRuntime() :

        mExitWithoutCleanup(false)

{

//图形相关的初始化,skia库初始化。

    SkGraphics::Init();

    SkImageDecoder::SetDeviceConfig(SkBitmap::kRGB_565_Config);

    SkImageRef_GlobalPool::SetRAMBudget(512 * 1024);

    mOptions.setCapacity(20);

    assert(gCurRuntime == NULL);       

    gCurRuntime = this; // gCurRuntime被设置为AndroidRuntime对象自己

}

 

由于SS是从zygote fork出来的,所以它也拥有zygote进程中定义的这个gCurRuntime对象,那么onZygoteInit有什么作用呢?它的代码在App_main.cpp中:

virtual void onZygoteInit()

    {

        atrace_set_tracing_enabled(true);

//这个函数与binder有关,暂时不细究~

        sp<ProcessState> proc = ProcessState::self();

        ALOGV("App process: starting thread pool.\n");

        proc->startThreadPool(); //启动一个线程,用于Binder通信

    }

 

一言以蔽之,SS调用nativeZygoteInit后,将于Binder通信系统建立联系,这样SS就能够使用binder了。关于Binder的知识,将在后面详细介绍,这里不过多关注。

2、applicationInit分析

applicationInit主要是完成SS的应用层(java层)的初始化工作,该函数的核心功能在invokeStaticMain函数中:

    private static void invokeStaticMain(String className, String[] argv)

            throws ZygoteInit.MethodAndArgsCaller {

//传递进来的参数className = “com.android.server.SystemServer”

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

        }

        /*

         * This throw gets caught in ZygoteInit.main(), which responds

         * by invoking the exception‘s run() method. This arrangement

         * clears up all the stack frames that were required in setting

         * up the process.

         */

       /*重点来了!!!这里竟然抛出了一个异常!从源代码的注释可以知道,这个异常被ZygoteInit.main()截获(注意:我们此时是在SS进程中),然后调用该异常的run函数。

*/

        throw new ZygoteInit.MethodAndArgsCaller(m, argv);

}

 

/*回到zygoteinit.java的main函数看一下这个run 函数的功能*/

public void run() {

            try {

/*这个mMethod是com.android.server.SystemServer的main函数*/

                mMethod.invoke(null, new Object[] { mArgs });

            } catch (IllegalAccessException ex) {

                ……

        }

 

可以看出,invokeStaticMain抛出异常后会导致zygote进程调用com.android.server.SystemServer的main函数。那么为什么不直接在invokeStaticMain里面调用,转而使用这种方法呢?这个涉及到堆栈调用相关的只是,笔者还没弄明白,暂时搁置~

3、SS的真面目

Zygoteinit分裂产生的SS其实就是为了调用com.android.server.SystemServer的main函数!那么我们来看一看这个main函数到底做了什么:

public static void main(String[] args) {

         ……..

        // Mmmmmm... more memory!这尼玛是在搞笑?

        dalvik.system.VMRuntime.getRuntime().clearGrowthLimit();

          ……

        //加载libandroid_servers.so库

        System.loadLibrary("android_servers");

 

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

 

        // 调用native函数,初始化native服务,其实就完成一个功能:

判断服务是否为sensor服务,如果是,就启动之。

        nativeInit();

 

        // This used to be its own separate thread, but now it is

        // just the loop we run on the main thread.

        ServerThread thr = new ServerThread(); //创建一个服务线程

        thr.initAndLoop(); //重点在这个函数!

}

}

initAndLoop函数完成了SS真正的功能:启动系统各项重要的服务,然后此线程进行消息循环,接收和处理消息。

1.3 对SS的总结

SS的启动流程:

Zygoteinit调用startSystemServer创建System_server进程;SS调用hanleSystemServerProcess完成自己的使命;hanleSystemServerProcess抛出异常MethodAndArgsCaller,最终调用com.android.server.SystemServer的main函数;main函数创建一个ServerThread线程,再调用这个线程的initAndLoop函数;在这个initAndLoop函数中,启动系统各项重要的服务,并将该线程加入到Binder通信系统中,进行消息循环。

SystemServer分析,布布扣,bubuko.com

SystemServer分析

标签:android   c   class   code   java   tar   

原文地址:http://www.cnblogs.com/wanyuanchun/p/3746660.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!