Android 启动过程分析 (一)

本文主要介绍 Android 系统的启动过程,以 Androidinit 进程之后部分为主, init 之前部分同标准 Linux 内核启动完全相同。于 Android 启动过程复杂,涉及 C C++ java 部分内容,本文以流程分析为主线旨在让大家在分析 Android 系统时有个清晰的思路。鉴于本人水平有限,如有阐述不正之处,还请不吝指正,感激不尽!

系统启动大致可分为一下几个阶段:

  • bootloader---初始化、从Flash读取Kernel镜像及一些必须的配置信息,引导kernel启动

  • linuxkernel启动linux内核

  • init进程启动

  • init进程读取init.rc启动必要的daemon程序,如:adbdvoldnetd、等

  • init进程启动servicemanager---随后详细分析其过程

  • init进程启动zygote ---随后详细分析其过程

  • JAVA部分的Service启动
  • init进程启动mediaserver---多媒体本地服务启动

本文主要分析android部分的启动,涉及范围为servicemanager启动到android系统的Java部分的Service;

    1. servicemanager启动

首先看init.rc中的servicemanager启动命令如下:

serviceservicemanager /system/bin/servicemanager

其执行源码位于:frameworks/base/cmds/servicemanager

文件:Android.mk bctest.c binder.c binder.h service_manager.c

service_manager.c main函数:
struct binder_state
{
    int fd;
    void *mapped;
    unsigned mapsize;
};
#define BINDER_SERVICE_MANAGER ((void*) 0)
int main(int argc, char **argv)
{
    struct binder_state *bs;
    void *svcmgr = BINDER_SERVICE_MANAGER; 
    bs = binder_open(128*1024);  
//打开binder设备,执行binder相应的初始化,构建一个binder_state对象
    if (binder_become_context_manager(bs)) {    
//将这个binder_state设置为manger,整个系统仅此一个manger
        LOGE("cannot become context manager (%s)\n", strerror(errno));
        return -1;
    }
    svcmgr_handle = svcmgr;   
    binder_loop(bs, svcmgr_handler); 
 /*循环处理针对上面定义的bs对象的所有操作,svcmgr_handler作为处理函数,真正处理针对这个系统唯一的manger binder对象的所有操作;
总结svcmgr_handler处理的操作有:
获取service
查看service是否存在
添加service
列出service清单 
		这是servicemanager 的核心,用的最多的就是获取、添加;当然从具体的实现代码可以看出,service的实现完全依赖与binder机制,设置该函数构建的binder对象为系统唯一的manager是通过ioctl操作binder驱动来实现的;
*/
    return 0;
}

svcmgr_handler 的处理函数如下:
int svcmgr_handler(struct binder_state *bs,
                   struct binder_txn *txn,
                   struct binder_io *msg,
                   struct binder_io *reply)
{
    struct svcinfo *si;
    uint16_t *s;
    unsigned len;
    void *ptr;
    uint32_t strict_policy;
  
    if (txn->target != svcmgr_handle)
        return -1;
    // Equivalent to Parcel::enforceInterface(), reading the RPC
    // header with the strict mode policy mask and the interface name.
    // Note that we ignore the strict_policy and don't propagate it
    // further (since we do no outbound RPCs anyway).
    strict_policy = bio_get_uint32(msg);
    s = bio_get_string16(msg, &len);
    if ((len != (sizeof(svcmgr_id) / 2)) ||
        memcmp(svcmgr_id, s, sizeof(svcmgr_id))) {
        fprintf(stderr,"invalid id %s\n", str8(s));
        return -1;
    }

    switch(txn->code) {
    case SVC_MGR_GET_SERVICE:
    case SVC_MGR_CHECK_SERVICE:
        s = bio_get_string16(msg, &len);
        ptr = do_find_service(bs, s, len);
        if (!ptr)
            break;
        bio_put_ref(reply, ptr);
        return 0;

    case SVC_MGR_ADD_SERVICE:
        s = bio_get_string16(msg, &len);
        ptr = bio_get_ref(msg);
        if (do_add_service(bs, s, len, ptr, txn->sender_euid))
            return -1;
        break;

    case SVC_MGR_LIST_SERVICES: {
        unsigned n = bio_get_uint32(msg);

        si = svclist;
        while ((n-- > 0) && si)
            si = si->next;
        if (si) {
            bio_put_string16(reply, si->name);
            return 0;
        }
        return -1;
    }
    default:
        LOGE("unknown code %d\n", txn->code);
        return -1;
    }
    bio_put_uint32(reply, 0);
    return 0;
}
struct svcinfo 
{
    struct svcinfo *next;
    void *ptr;
    struct binder_death death;
    unsigned len;
    uint16_t name[0];
};

struct svcinfo *svclist = 0;

所有的service由全局指针变量svclist指向的链表来维护,其主要包括servicenamehandle等;其中namehandle都是添加service时通过binder传递过来的;具体可依据前面路径给粗的代码分析;

至此,servicemanger启动分析完成,该进程一直在binder_loop的死循环中等待处理service相关的各种请求;


    2.    Zygote启动

init.rc可知接下来init进程会启动zygote

servicezygote /system/bin/app_process -Xzygote /system/bin --zygote--start-system-server

由启动命令可知zygote实际执行的是app_process

其源码位于:frameworks/base/cmds/app_process


文件:Android.mk app_main.cpp只有一个app_main.cpp文件

我们先进入该文件的main函数分析:

int main(int argc, const char* const argv[])
{
    // 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 *arg;
    const char *argv0;

    argv0 = argv[0];
    // Process command line arguments
/*  实际真正执行的命令: system/bin/app_process -Xzygote /system/bin --zygote –start-system-server
argc = 5;
argv[0] = “system/bin/app_process”;
argv[1] = “-Xzygote”;
argv[2] = “/system/bin”;
argv[3] = “--zygote”;
argv[4] = “–start-system-server”;
*/
    // ignore argv[0]
    argc--;
    argv++;
/* 此时 argc = 4 ,argv[0] 指向 -Xzygote,以此类推  */
    // Everything up to '--' or first non '-' arg goes to the vm
      int i = runtime.addVmArguments(argc, argv);
/* 经过runtime.addVmArguments()函数处理返回的 i=1,这里不列出该函数的详细代码,如有兴趣请查源码分析              */
    // Next arg is parent directory
    if (i < argc) {
        runtime.mParentDir = argv[i++];
/* runtime.mParentDir = argv[1] = “/system/bin” ,之后 i=2  */
    }

    // Next arg is startup classname or "--zygote"
    if (i < argc) {
        arg = argv[i++];
        if (0 == strcmp("--zygote", arg)) {
            bool startSystemServer = (i < argc) ? strcmp(argv[i], "--start-system-server") == 0 : false;
/*  startSystemServer = true ,这个bool变量决定着后面执行runtime.start时是否启动systemserver,
其实就是启动java 部分的所有service,这里启动的所有service会被添加到前面的servicemanager的service 列表中,
并由其来进行管理源码位置:frameworks\base\services\java\com\android\server\*   */
            setArgv0(argv0, "zygote");   
            set_process_name("zygote");   //设置进程名
            runtime.start("com.android.internal.os.ZygoteInit", startSystemServer);
	//执行AndroidRuntime::start函数,不再返回,改进成就是zygote进程
        } else {
            set_process_name(argv0);
            runtime.mClassName = arg;
            // Remainder of args get passed to startup class main()
            runtime.mArgC = argc-i;
            runtime.mArgV = argv+i;
            LOGV("App process is starting with pid=%d, class=%s.\n",
                 getpid(), runtime.getClassName());
            runtime.start();
        }
    } else {
        LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
        fprintf(stderr, "Error: no class name or --zygote supplied.\n");
        app_usage();
        return 10;
    }
}

下面进一步分析: runtime.start("com.android.internal.os.ZygoteInit",startSystemServer);

源码位置:AndroidRuntime.cpp(frameworks\base\core\jni)

void AndroidRuntime::start(const char* className, const bool startSystemServer)
{
    LOGD("\n>>>>>> AndroidRuntime START %s <<<<<<\n", className != NULL ? className : "(unknown)");
    char* slashClassName = NULL;
    char* cp;
    JNIEnv* env;

    blockSigpipe();

    /* 'startSystemServer == true' means runtime is obslete and not run from 
     * init.rc anymore, so we print out the boot start event here.    */
    if (startSystemServer) {
        /* 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.");
            goto bail;
        }
        setenv("ANDROID_ROOT", rootDir, 1);
    }
    //const char* kernelHack = getenv("LD_ASSUME_KERNEL");
    //LOGD("Found LD_ASSUME_KERNEL='%s'\n", kernelHack);
    /* start the virtual machine */
//启动一个Dalvic虚拟机,需要执行许多寄存器等方面的复杂工作,这里不做分析,后面有时间单独分析,我们简单认为启动了一个虚拟机即可;
    if (startVm(&mJavaVM, &env) != 0)   
        goto bail;
    /* Register android functions.     */
    if (startReg(env) < 0) {
        LOGE("Unable to register all android natives\n");
        goto bail;
    }

    /*    * We want to call main() with a String array with arguments in it.     * At present we only have one argument, the class name.  Create an array to hold it.     */
/*我们目前只有有一个类名,我们需要调用相关函数以一个String类型的数组来保存其参数,下面来构建这个参数数组*/
    jclass stringClass;
    jobjectArray strArray;
    jstring classNameStr;
    jstring startSystemServerStr;

    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);
    startSystemServerStr = env->NewStringUTF(startSystemServer ? 
                                                 "true" : "false");
    env->SetObjectArrayElement(strArray, 1, startSystemServerStr);
/*  新的string class  strArray[0] = “true”;
strArray[1] = “com.android.internal.os.ZygoteInit”;
*/
    /*     * Start VM.  This thread becomes the main thread of the VM, and will
     * not return until the VM exits.     */
    jclass startClass;
    jmethodID startMeth;
    slashClassName = strdup(className);
    for (cp = slashClassName; *cp != '\0'; cp++)
        if (*cp == '.')
            *cp = '/';
/* slashClassName = “com/android/internal/os/ZygoteInit”     */
    startClass = env->FindClass(slashClassName);
    if (startClass == NULL) {
        LOGE("JavaVM unable to locate class '%s'\n", slashClassName);
        /* keep going */
    } else {
/*这个参数决定了我们接下来执行的是zygoteInit.java的main函数  */     
   startMeth = env->GetStaticMethodID(startClass, "main",
            "([Ljava/lang/String;)V");
        if (startMeth == NULL) {
            LOGE("JavaVM unable to find main() in '%s'\n", className);
            /* keep going */
        } else {
            env->CallStaticVoidMethod(startClass, startMeth, strArray);
/*这个函数启动Dalvik虚拟机后执行的最重要的函数就是这个函数,通过jni调用 com/android/internal/os/ZygoteInit包的main函数,
参数 strArray[0] = “true”;strArray[1] = “com.android.internal.os.ZygoteInit”; 
调用之后不再返回这里;*/

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

下面我们继续分析 zygoteInit main 函数,这也正是 zygote 进程进一步执行的路线:

源码位置:frameworks\base\core\java\com\android\internal\os\ZygoteInit.java

publicstatic void main(String argv[]) {

try{

VMRuntime.getRuntime().setMinimumHeapSize(5* 1024 * 1024);

//Start profiling the zygote initialization.

SamplingProfilerIntegration.start();

registerZygoteSocket(); /* 注册zygotesocket */

EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,

SystemClock.uptimeMillis());

preloadClasses(); /* 加载必要的类 */

//cacheRegisterMaps();

preloadResources(); /* 加载必要的资源 */

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(); /*初始化GC垃圾回收机制*/

//If requested, start system server directly from Zygote

if(argv.length != 2) {

thrownew RuntimeException(argv[0] + USAGE_STRING);

}

/* 上阶段分析是传递过来的参数列表的第二个参数,也就是startsystemserver=”true” 启动systemserver,
在startSystemServer函数中会fork一个新的进程命名为system_server执行的是com.android.server包中的SystemServer.java文件中的main函数,
源码位置:frameworks/base/services/java/com/android/server/,具体功能后面分析;*/

if(argv[1].equals("true")) {

startSystemServer();

}else if (!argv[1].equals("false")) {

thrownew RuntimeException(argv[0] + USAGE_STRING);

}

/*Zygote 进程继续执行,这也正是Zygote进程的主要功能就是孵化新的进程 */

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

if(ZYGOTE_FORK_MODE) { /* ZYGOTE_FORK_MODE 永远为flase */

runForkMode();

}else {

runSelectLoopMode(); /* Zygote进程进入无限循环,不再返回,执行孵化工作具体下面接着分析 */

}

closeServerSocket();

}catch (MethodAndArgsCaller caller) {

caller.run();

}catch (RuntimeException ex) {

Log.e(TAG,"Zygote died with exception", ex);

closeServerSocket();

throwex;

}

} 

从这里开始android启动分为两条线走,分别是:

startSystemServer(); ---------- Zygote的子进程

runSelectLoopMode(); /* Zygote进程进入无限循环,不再返回,执行孵化工作具体下面接着分析 */


未完待叙-----

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值