android zygote 进程与system service进程的启动过程浅析。

android 系统启动时调用的相关文件路径:

Z:\mocor_sc9820w_new\mocor_sc9820\system\core\rootdir\init.rc

Z:\mocor_sc9820w_new\mocor_sc9820\frameworks\base\cmds\app_process\app_main.cpp

Z:\mocor_sc9820w_new\mocor_sc9820\frameworks\base\core\jni\AndroidRuntime.cpp

Z:\mocor_sc9820w_new\mocor_sc9820\frameworks\base\core\java\com\android\internal\os\ZygoteInit.java

Z:\mocor_sc9820w_new\mocor_sc9820\system\core\init\init.c

Z:\mocor_sc9820w_new\mocor_sc9820\frameworks\base\services\java\com\android\server\SystemServer.java

C语言的入口函数:

int main(int argc, char* const argv[]) argc 参数的个数,argc 参数。

Java的入口函数: 

public static void main(String argv[])没有返回值,必须为void。

android app 上层是java写的,通过编译,生成.class文件,class文件通过sdk包中的dex工具,将class文件转换为dex文件,运行在虚拟机上。
应用程序通过binder ipc 访问系统服务,系统服务通过jni访问hal module用户空间部分设备,hal module通过设备文件访问内核空间设备驱动。

android 专用驱动是以Linux驱动的形式实现在linux内核空间,android专用驱动主要有:
1.高效的日志服务。
2.高效的进程间通信机制
3.以组件为目标的进程管理机制。

它的目的不是为了驱动硬件设备工作而是为了获得特权管理系统,它是为android runtime framework应用框架层服务。
AMS 启动一个应用程序的时候,会通过socket与zygote进程进行通信,请求他fork一个子进程出来作为这个即将启动的应用的的进程。

1.创建zygote进程的过程:
AMS 和 PMS 服务都是有systemService服务进程启动的,而systemService服务进程是有zygote服务进程在启动的过程中孕育出来的,
然而我们都知道android是基于Linux内核,而Linux内核系统中,所有的进程但是init进程的子孙进程,也就是说所以的进程都是直接或者
间接的有init进程fork出来的,zygote也不例外,它是在系统启动过程中,有init进行创建的,在系统启动的脚本system/core/rootdir/init.rc
文件中,我们可以看到启动zygote进程的脚本命令:
service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server  
    socket zygote stream 666  
    onrestart write /sys/android_power/request_state wake  
    onrestart write /sys/power/state on  
    onrestart restart media  
    onrestart restart netd  

Step 1. app_process.main
了解了这个信息之后,我们就知道Zygote进程要执行的程序便是system/bin/app_process了,它的源代码位于frameworks/base/cmds/app_process/
app_main.cpp文件中,入口函数是main。
在framework/base/cmds/app_process/app_main.cpp的main函数中主要做了如下事情:
int main(int argc, char* const argv[])
{
/* @SPRD: Add log for performance test. @{ */
    BOOTINFO("Zygote process start \n");
/* @} */
#ifdef __arm__
    /*
     * b/7188322 - Temporarily revert to the compat memory layout
     * to avoid breaking third party apps.
     *
     * THIS WILL GO AWAY IN A FUTURE ANDROID RELEASE.
     *
     * http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commitdiff;h=7dbaa466
     * changes the kernel mapping from bottom up to top-down.
     * This breaks some programs which improperly embed
     * an out of date copy of Android's linker.
     */
    char value[PROPERTY_VALUE_MAX];
    property_get("ro.kernel.qemu", value, "");
    bool is_qemu = (strcmp(value, "1") == 0);
    if ((getenv("NO_ADDR_COMPAT_LAYOUT_FIXUP") == NULL) && !is_qemu) {
        int current = personality(0xFFFFFFFF);
        if ((current & ADDR_COMPAT_LAYOUT) == 0) {
            personality(current | ADDR_COMPAT_LAYOUT);
            setenv("NO_ADDR_COMPAT_LAYOUT_FIXUP", "1", 1);
            execv("/system/bin/app_process", argv);
            return -1;
        }
    }
    unsetenv("NO_ADDR_COMPAT_LAYOUT_FIXUP");
#endif
    // These are global variables in ProcessState.cpp
    mArgC = argc;
    mArgV = argv;
    mArgLen = 0;
    for (int i=0; i<argc; i++) {
        mArgLen += strlen(argv[i]) + 1;
    }
    mArgLen--;
    AppRuntime runtime;
    const char* argv0 = argv[0];
   // Process command line arguments
    // ignore argv[0]
    argc--;
    argv++;
    // Everything up to '--' or first non '-' arg goes to the vm


    int i = runtime.addVmArguments(argc, argv);

    // Parse runtime arguments.  Stop at first unrecognized option.
    bool zygote = false;
    bool startSystemServer = false;
    bool application = false;
    const char* parentDir = NULL;
    const char* niceName = NULL;
    const char* className = NULL;
    while (i < argc) {
        const char* arg = argv[i++];
        if (!parentDir) {
            parentDir = arg;
        } else if (strcmp(arg, "--zygote") == 0) {
            zygote = true;
            niceName = "zygote";
        } else if (strcmp(arg, "--start-system-server") == 0) {
            startSystemServer = true;
        } else if (strcmp(arg, "--application") == 0) {
            application = true;
        } else if (strncmp(arg, "--nice-name=", 12) == 0) {
            niceName = arg + 12;
        } else {
            className = arg;
            break;
        }
    }
   if (niceName && *niceName) {
        setArgv0(argv0, niceName);
        set_process_name(niceName);
    }
    runtime.mParentDir = parentDir;
    BOOTINFO("before zygote \n");
    if (zygote) {
        /** SPRD: clear dalvik cache when last shutdown abnormal @{ */
        // do last shutdown check
        BOOTINFO("doLastShutDownCheck \n");
        doLastShutDownCheck();
        /** @} */
        runtime.start("com.android.internal.os.ZygoteInit",
                startSystemServer ? "start-system-server" : "");
    } else if (className) {
        // Remainder of args get passed to startup class main()
        BOOTINFO("zygote main class \n");
        runtime.mClassName = className;
        runtime.mArgC = argc - i;
        runtime.mArgV = argv + i;
        runtime.start("com.android.internal.os.RuntimeInit",
                application ? "application" : "tool");
    } else {
        fprintf(stderr, "Error: no class name or --zygote supplied.\n");
        app_usage();
        LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
        return 10;
    }
}

在这个main函数中主要就是创建了一个App runtime变量,最后执行的是AppRuntime的成员方法start。

而AppRutime它也继承以AndroidRuntime,当AppRuntime对象被创建时,它会调用其父类AndroidRuntime的构造函数,

而在AndroidRuntime的构造函数中,会将this指针保存在静态全局变量gCurRuntime中,这样当其他的的地方需要使用

AndroidRuntime对象时,就可以通过同一个文件的这个函数来获取这个对象的指针。


回到上面的main方法中,由于我们在init.rc文件中设置了启动参数为 --zygote 和 --start-system-service,因此在main方法里面,最终会执行下面语句。
        runtime.start("com.android.internal.os.ZygoteInit",
                startSystemServer ? "start-system-server" : "");
这里的startSystemServer==true,表示启动systemServer组件,而由于AppRuntime类是没有实现自己的start方法,它用的是AndroidRuntime中的start函数。

Step 2. AndroidRuntime.start
个函数定义在frameworks/base/core/jni/AndroidRuntime.cpp文件中:
void AndroidRuntime::start(const char* className, const char* options)
{
    BOOTINFO("\n>>>>>> AndroidRuntime START %s <<<<<<\n",
            className != NULL ? className : "(unknown)");


    /* SPRD: add for apct functions @{ */
    char buf[2][128] = {'\0'};
    nsecs_t time0;
    uint32_t time1;
    /* @} */


    /*
     * 'startSystemServer == true' means runtime is obsolete and not run from
     * init.rc anymore, so we print out the boot start event here.
     */
    if (strcmp(options, "start-system-server") == 0) {
        /* track our progress through the boot sequence */
        const int LOG_BOOT_PROGRESS_START = 3000;
        LOG_EVENT_LONG(LOG_BOOT_PROGRESS_START,
                       ns2ms(systemTime(SYSTEM_TIME_MONOTONIC)));
    }


    const char* rootDir = getenv("ANDROID_ROOT");
    if (rootDir == NULL) {
        rootDir = "/system";
        if (!hasDir("/system")) {
            LOG_FATAL("No root directory specified, and /android does not exist.");
            return;
        }
        setenv("ANDROID_ROOT", rootDir, 1);
    }


    //const char* kernelHack = getenv("LD_ASSUME_KERNEL");
    //ALOGD("Found LD_ASSUME_KERNEL='%s'\n", kernelHack);


    /* SPRD: add for apct functions @{ */
    if (getApctBootDataSupport())
    {
        time0 = systemTime();
    }
    /* @} */


    /* start the virtual machine */
    JniInvocation jni_invocation;
    jni_invocation.Init(NULL);
    JNIEnv* env;
    if (startVm(&mJavaVM, &env) != 0) {
        return;
    }


    /* SPRD: add for apct functions @{ */
    if (getApctBootDataSupport())
    {
        time1 = (uint32_t)ns2ms(systemTime() - time0);
        sprintf(buf[0], "BOOTING: start JVM takes: %d ms", time1);
    }
    /* @} */


    onVmCreated(env);


    /* SPRD: add for apct functions @{ */
    if (getApctBootDataSupport())
    {
        time0 = systemTime();
    }
    /* @} */


    /*
     * Register android functions.
     */
    if (startReg(env) < 0) {
        ALOGE("Unable to register all android natives\n");
        return;
    }


    /* SPRD: add for apct functions @{ */
    if (getApctBootDataSupport())
    {
        time1 = (uint32_t)ns2ms(systemTime() - time0);
        sprintf(buf[1], "BOOTING: Register JNI takes: %d ms", time1);


        char *buf_log = (char*)malloc(256);
        sprintf(buf_log, "%s\n%s\n", buf[0], buf[1]);
        writeInitProcess(buf_log);
        free(buf_log);
    }
    /* @} */


    /*
     * We want to call main() with a String array with arguments in it.
     * At present we have two arguments, the class name and an option string.
     * Create an array to hold them.
     */
    jclass stringClass;
    jobjectArray strArray;
    jstring classNameStr;
    jstring optionsStr;


    stringClass = env->FindClass("java/lang/String");
    assert(stringClass != NULL);
    strArray = env->NewObjectArray(2, stringClass, NULL);
    assert(strArray != NULL);
    classNameStr = env->NewStringUTF(className);
    assert(classNameStr != NULL);
    env->SetObjectArrayElement(strArray, 0, classNameStr);
    optionsStr = env->NewStringUTF(options);
    env->SetObjectArrayElement(strArray, 1, optionsStr);


    /*
     * Start VM.  This thread becomes the main thread of the VM, and will
     * not return until the VM exits.
     */
    char* slashClassName = toSlashClassName(className);
    jclass startClass = env->FindClass(slashClassName);
    BOOTINFO("start class before zygote init \n");
    if (startClass == NULL) {
        ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);
        /* keep going */
    } else {
        jmethodID startMeth = env->GetStaticMethodID(startClass, "main",
            "([Ljava/lang/String;)V");
        if (startMeth == NULL) {
            ALOGE("JavaVM unable to find main() in '%s'\n", className);
            /* keep going */
        } else {
            env->CallStaticVoidMethod(startClass, startMeth, strArray);


#if 0
            if (env->ExceptionCheck())
                threadExitUncaughtException(env);
#endif
        }
    }
    free(slashClassName);
    ALOGD("Shutting down VM\n");
    if (mJavaVM->DetachCurrentThread() != JNI_OK)
        ALOGW("Warning: unable to detach main thread\n");
    if (mJavaVM->DestroyJavaVM() != 0)
        ALOGW("Warning: VM did not shut down cleanly\n");
}

这个函数的的作用主要是:启动了android系统运行时库,它主要做的三件事是:一是调用了startVM启动了虚拟机,而是调用了

函数startReg注册jni方法,三是调用了com.android.internal.os.ZygoteInit类的main函数。

Step 3. ZygoteInit.main
这个函数定义在frameworks/base/core/java/com/android/internal/os/ZygoteInit.java文件中:
public class ZygoteInit {  
    ......  


  public static void main(String argv[]) {
        try {
            Log.i(TAG, "zygote init main");
            // Start profiling the zygote initialization.
            SamplingProfilerIntegration.start();


            registerZygoteSocket();
            EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,
                    SystemClock.uptimeMillis());


            /* @SPRD: Add log for performance test. @{ */
            boolean performanceTest = Log.isPerformanceTestable();
            if (performanceTest) {
                Log.startPerfTracking("ZytoteInit" + " preload");
            }


            /* @} */


            preload();


            /* @SPRD: Add log for performance test. @{ */
            if (performanceTest) {
               Log.stopPerfTracking("ZytoteInit" + " preload");
            }
            Log.i(TAG, "ZytoteInit" + " preload finish");
            /* @} */


            EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,
                    SystemClock.uptimeMillis());


            // Finish profiling the zygote initialization.
            SamplingProfilerIntegration.writeZygoteSnapshot();


            // Do an initial gc to clean up after startup
            gc();


            // Disable tracing so that forked processes do not inherit stale
            // tracing tags from
            // Zygote.
            Trace.setTracingEnabled(false);


            // If requested, start system server directly from Zygote
            if (argv.length != 2) {
                throw new RuntimeException(argv[0] + USAGE_STRING);
            }


            if (argv[1].equals("start-system-server")) {
                startSystemServer();
            } else if (!argv[1].equals("")) {
                throw new RuntimeException(argv[0] + USAGE_STRING);
            }


            Log.i(TAG, "Accepting command socket connections");


            runSelectLoop();


            closeServerSocket();
        } catch (MethodAndArgsCaller caller) {
            caller.run();
        } catch (RuntimeException ex) {
            Log.e(TAG, "Zygote died with exception", ex);
            closeServerSocket();
            throw ex;
        }
    }
}

这个zygoteInit主要做了三件事情:
首先registerZygoteSocket();函数创建了一个socket接口,用来和AMS通讯。
其次startSystemServer();启动了系统服务组件。
最后runSelectLoop();函数进入了一个无限循环,在前面创建的socket接口上等待ams请求创建新的应用程序进程。

Step 4. ZygoteInit.registerZygoteSocket
public class ZygoteInit {  
    ......  


    private static final String ANDROID_SOCKET_ENV = "ANDROID_SOCKET_zygote";


    private static void registerZygoteSocket() {
        if (sServerSocket == null) {
            int fileDesc;
            try {
                String env = System.getenv(ANDROID_SOCKET_ENV);
                fileDesc = Integer.parseInt(env);
            } catch (RuntimeException ex) {
                throw new RuntimeException(
                        ANDROID_SOCKET_ENV + " unset or invalid", ex);
            }


            try {
                sServerSocket = new LocalServerSocket(
                        createFileDescriptor(fileDesc));
            } catch (IOException ex) {
                throw new RuntimeException(
                        "Error binding to local socket '" + fileDesc + "'", ex);
            }
        }
    }
}
这个zygote socket 的创建是通过文件描述符创建的,这个文件描述符代表的就是我们前面说的/dev/socket/zygote文件,这个
文件描述符是通过环境变量ANDROID_SOCKET_ENV得到的。

同样有个疑问,你们这个环境变量的值是谁赋予的?我们知道系统启动脚本是system/core/rootdir/init.rc文件,而init.rc文件是
有init进程来解释执行的,而init进程的源代码位于system/core/init/init.c文件中,是由init.c文件中的service_start函数来
解释init.rcwenj

void service_start(struct service *svc, const char *dynamic_args)
{
    struct stat s;
    pid_t pid;
    int needs_console;
    int n;
    char *scon = NULL;
    int rc;


        /* starting a service removes it from the disabled or reset
         * state and immediately takes it out of the restarting
         * state if it was in there
         */
    svc->flags &= (~(SVC_DISABLED|SVC_RESTARTING|SVC_RESET|SVC_RESTART));
    svc->time_started = 0;
    if((!strncmp(svc->name,"healthd",7))&&(!strcmp(bootmode, "charger"))){
         ERROR("stopping '%s'\n", svc->name);
         svc->flags |= SVC_DISABLED;
         return;
    }
        /* running processes require no additional work -- if
         * they're in the process of exiting, we've ensured
         * that they will immediately restart on exit, unless
         * they are ONESHOT
         */
    if (svc->flags & SVC_RUNNING) {
        return;
    }


    needs_console = (svc->flags & SVC_CONSOLE) ? 1 : 0;
    if (needs_console && (!have_console)) {
        ERROR("service '%s' requires console\n", svc->name);
        svc->flags |= SVC_DISABLED;
        return;
    }


    if (stat(svc->args[0], &s) != 0) {
        ERROR("cannot find '%s', disabling '%s'\n", svc->args[0], svc->name);
        svc->flags |= SVC_DISABLED;
        return;
    }


    if ((!(svc->flags & SVC_ONESHOT)) && dynamic_args) {
        ERROR("service '%s' must be one-shot to use dynamic args, disabling\n",
               svc->args[0]);
        svc->flags |= SVC_DISABLED;
        return;
    }


    if (is_selinux_enabled() > 0) {
        if (svc->seclabel) {
            scon = strdup(svc->seclabel);
            if (!scon) {
                ERROR("Out of memory while starting '%s'\n", svc->name);
                return;
            }
        } else {
            char *mycon = NULL, *fcon = NULL;


            INFO("computing context for service '%s'\n", svc->args[0]);
            rc = getcon(&mycon);
            if (rc < 0) {
                ERROR("could not get context while starting '%s'\n", svc->name);
                return;
            }


            rc = getfilecon(svc->args[0], &fcon);
            if (rc < 0) {
                ERROR("could not get context while starting '%s'\n", svc->name);
                freecon(mycon);
                return;
            }


            rc = security_compute_create(mycon, fcon, string_to_security_class("process"), &scon);
            freecon(mycon);
            freecon(fcon);
            if (rc < 0) {
                ERROR("could not get context while starting '%s'\n", svc->name);
                return;
            }
        }
    }

   NOTICE("starting '%s'\n", svc->name);

    pid = fork();

    if (pid == 0) {
        struct socketinfo *si;
        struct svcenvinfo *ei;
        char tmp[32];
        int fd, sz;
        umask(077);
        if(!strcmp(svc->name, "zygote")){
            BOOTINFO("service_start name is %s \n", svc->name);
        }
        if (properties_inited()) {
            get_property_workspace(&fd, &sz);
            sprintf(tmp, "%d,%d", dup(fd), sz);
            add_environment("ANDROID_PROPERTY_WORKSPACE", tmp);
        }


        for (ei = svc->envvars; ei; ei = ei->next)
            add_environment(ei->name, ei->value);


        setsockcreatecon(scon);


        for (si = svc->sockets; si; si = si->next) {
            int socket_type = (
                    !strcmp(si->type, "stream") ? SOCK_STREAM :
                        (!strcmp(si->type, "dgram") ? SOCK_DGRAM : SOCK_SEQPACKET));
            int s = create_socket(si->name, socket_type,
                                  si->perm, si->uid, si->gid);
            if (s >= 0) {
                publish_socket(si->name, s);
            }
        }


        freecon(scon);
        scon = NULL;
        setsockcreatecon(NULL);


        if (svc->ioprio_class != IoSchedClass_NONE) {
            if (android_set_ioprio(getpid(), svc->ioprio_class, svc->ioprio_pri)) {
                ERROR("Failed to set pid %d ioprio = %d,%d: %s\n",
                      getpid(), svc->ioprio_class, svc->ioprio_pri, strerror(errno));
            }
        }


        if (needs_console) {
            setsid();
            open_console();
        } else {
            zap_stdio();
        }


#if 0
        for (n = 0; svc->args[n]; n++) {
            INFO("args[%d] = '%s'\n", n, svc->args[n]);
        }
        for (n = 0; ENV[n]; n++) {
            INFO("env[%d] = '%s'\n", n, ENV[n]);
        }
#endif


        setpgid(0, getpid());


    /* as requested, set our gid, supplemental gids, and uid */
        if (svc->gid) {
            if (setgid(svc->gid) != 0) {
                ERROR("setgid failed: %s\n", strerror(errno));
                _exit(127);
            }
        }
        if (svc->nr_supp_gids) {
            if (setgroups(svc->nr_supp_gids, svc->supp_gids) != 0) {
                ERROR("setgroups failed: %s\n", strerror(errno));
                _exit(127);
            }
        }
        if (svc->uid) {
            if (setuid(svc->uid) != 0) {
                ERROR("setuid failed: %s\n", strerror(errno));
                _exit(127);
            }
        }
        if (svc->seclabel) {
            if (is_selinux_enabled() > 0 && setexeccon(svc->seclabel) < 0) {
                ERROR("cannot setexeccon('%s'): %s\n", svc->seclabel, strerror(errno));
                _exit(127);
            }
        }
        if(!strcmp(svc->name, "zygote")){
            BOOTINFO("service_start end \n");
        }
        if (!dynamic_args) {
            if (execve(svc->args[0], (char**) svc->args, (char**) ENV) < 0) {
                ERROR("cannot execve('%s'): %s\n", svc->args[0], strerror(errno));
            }
        } else {
            char *arg_ptrs[INIT_PARSER_MAXARGS+1];
            int arg_idx = svc->nargs;
            char *tmp = strdup(dynamic_args);
            char *next = tmp;
            char *bword;


            /* Copy the static arguments */
            memcpy(arg_ptrs, svc->args, (svc->nargs * sizeof(char *)));


            while((bword = strsep(&next, " "))) {
                arg_ptrs[arg_idx++] = bword;
                if (arg_idx == INIT_PARSER_MAXARGS)
                    break;
            }
            arg_ptrs[arg_idx] = '\0';
            execve(svc->args[0], (char**) arg_ptrs, (char**) ENV);
        }
        _exit(127);
    }


    freecon(scon);


    if (pid < 0) {
        ERROR("failed to start '%s'\n", svc->name);
        svc->pid = 0;
        return;
    }


    svc->time_started = gettime();
    svc->pid = pid;
    svc->flags |= SVC_RUNNING;


    if (properties_inited())
        notify_service_state(svc->name, "running");
}


在init.rc文件中的每个服务命令,都会促使init.c文件中的service_start函数中的fork()为其创建一个新的进程,在新的进程里面,会分析里面的socket选项,
都会通过create_socket(si->name, socket_type,si->perm, si->uid, si->gid);在dev/socket/目录下创建一个文件,在zygote进程中,创建的便是zygote了,然后
得到的描述符通过publish_socket函数写入到环境变量中去。
static void publish_socket(const char *name, int fd)  
{  
    char key[64] = ANDROID_SOCKET_ENV_PREFIX;  
    char val[64];  
  
    strlcpy(key + sizeof(ANDROID_SOCKET_ENV_PREFIX) - 1,  
            name,  
            sizeof(key) - sizeof(ANDROID_SOCKET_ENV_PREFIX));  
    snprintf(val, sizeof(val), "%d", fd);  
    add_environment(key, val);  
  
    /* make sure we don't close-on-exec */  
    fcntl(fd, F_SETFD, 0);  
}  

当前zygote进程下,上面publish_socket的参数name为zygote,ANDROID_SOCKET_ENV_PREFIX在system/core/include/cutils/sockets.h定义为:
#define ANDROID_SOCKET_ENV_PREFIX   "ANDROID_SOCKET_" ,因此这里就把publish_socket得到的“ANDROID_SOCKET_zygote”为key值写入到环境变量中了。
同时ZygoteInit.registerZygoteSocket与init.c文件中的createSocket函数是同一个进程中,所以上面的ZygoteInit.registerZygoteSocket可以直接使用
这个符号描述符来创建一个LocalServiceSocket对象,如果其他的进程也需要打开这个dev/socket/zygote/文件与zygote进行进程间通信,那么需要使用
文件名来连接这个LocalServiceSocket了。

Step 5. Socket对象创建完成之后,回到Step 3中的ZygoteInit.main函数中,startSystemServer函数来启动SystemServer组件。
    private static boolean startSystemServer()
            throws MethodAndArgsCaller, RuntimeException {
        long capabilities = posixCapabilitiesAsBits(
            OsConstants.CAP_KILL,
            OsConstants.CAP_NET_ADMIN,
            OsConstants.CAP_NET_BIND_SERVICE,
            OsConstants.CAP_NET_BROADCAST,
            OsConstants.CAP_NET_RAW,
            OsConstants.CAP_SYS_MODULE,
            OsConstants.CAP_SYS_NICE,
            OsConstants.CAP_SYS_RESOURCE,
            OsConstants.CAP_SYS_TIME,
            OsConstants.CAP_SYS_TTY_CONFIG
        );
        /* Hardcoded command line to start the system server */
        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;
        /* SPRD: add for apct functions @{ */
        long time0 = 0;


        if (APCTOption.self().isApctBootDataSupport())
        {
            time0 = SystemClock.uptimeMillis();
        }
        /* @} */


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


            /* Request to fork the system server process */
            pid = Zygote.forkSystemServer(
                    parsedArgs.uid, parsedArgs.gid,
                    parsedArgs.gids,
                    parsedArgs.debugFlags,
                    null,
                    parsedArgs.permittedCapabilities,
                    parsedArgs.effectiveCapabilities);
        } catch (IllegalArgumentException ex) {
            throw new RuntimeException(ex);
        }


        /* For child process */
        if (pid == 0) {
            /* SPRD: add for apct functions @{ */
            if (APCTOption.self().isApctBootDataSupport())
            {
                long time1 = SystemClock.uptimeMillis() - time0;
                String str = "BOOTING: fork SystemServer takes: " + time1 + " ms\n";
                writeBootDataToProc(str);
            }
            /* @} */
            handleSystemServerProcess(parsedArgs);
        }


        return true;
    }

从这个函数中可以看到,通过Zygote.forkSystemSocket创建了一个新进程来启动systemService组件,返回值pid==0的地方就是新进程要执行的路径,
意思也就是新进程会执行handleSystemServerProcess函数。

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

        closeServerSocket();


        // set umask to 0077 so new files and directories will default to owner-only permissions.
        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 {
            /*
             * Pass the remaining arguments to SystemServer.
             */
            RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs);
        }
        /* should never reach here */
    }

由于zygote进程创建的子进程SystemSocket会继承zygote进程在Step 4. ZygoteInit.registerZygoteSocket中创建的socket文件描述符,而这里的子进程又不会用上它,
所以这里调用closeServerSocket();函数来关闭它。
Step 7. RuntimeInit.zygoteInit:

接着继续调用RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs);来执行启动systemService组件的操作。
    public static final void zygoteInit(int targetSdkVersion, String[] argv)
            throws ZygoteInit.MethodAndArgsCaller {
        if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting application from zygote");


        redirectLogStreams();


        commonInit();
        nativeZygoteInit();
        applicationInit(targetSdkVersion, argv);
    }
    private static void applicationInit(int targetSdkVersion, String[] argv)
            throws ZygoteInit.MethodAndArgsCaller {
        // If the application calls System.exit(), terminate the process
        // immediately without running any shutdown hooks.  It is not possible to
        // shutdown an Android application gracefully.  Among other things, the
        // Android runtime shutdown hooks close the Binder driver, which can cause
        // leftover running threads to crash before the process actually exits.
        nativeSetExitWithoutCleanup(true);


        // We want to be fairly aggressive about heap utilization, to avoid
        // holding on to a lot of memory that isn't needed.
        VMRuntime.getRuntime().setTargetHeapUtilization(0.75f);
        VMRuntime.getRuntime().setTargetSdkVersion(targetSdkVersion);
        final Arguments args;
        try {
            args = new Arguments(argv);
        } catch (IllegalArgumentException ex) {
            Slog.e(TAG, ex.getMessage());
            // let the process exit
            return;
        }

      // Remaining arguments are passed to the start class's static main
        invokeStaticMain(args.startClass, args.startArgs);
    }
这个函数中commonInit();函数中对时区,log日志,http用户代理,网络socket安装进行初始化。
用zygoteInitNative函数来执行一个Binder进程间通信机制的初始化工作,这个工作完成之后,这个进程中的Binder对象就可以方便地进行进程间通信了,这里可以看出,函数zygoteInitNative是一个Native函数,实现在frameworks/base/core/jni/AndroidRuntime.cpp文件中,Step 9,完成这一步后,这个进程的Binder进程间通信机制基础设施就准备好了。
applicationInit(targetSdkVersion, argv);中的invokeStaticMain(args.startClass, args.startArgs); 调用上面handleSystemServerProcess(parsedArgs);传进来的com.android.server.SystemServer类的main函数,执行com.android.server.SystemServer类的main函数了。

Step 8. SystemServer.main
这个函数定义在frameworks/base/services/java/com/android/server/SystemServer.java文件中:

















































  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值