深入理解Android-Init理解

这篇文章的意义在于理解Android的启动流程,作为一名应用开发者理论上应该知道从native世界到Java世界是怎么一步一步来的,进而理解Android的启动流程:
先看看可参考的三张启动流程图:

这里写图片描述

这里写图片描述

这里写图片描述

其中init进程起着承上启下的作用,android本身是基于Linux而来的,init进程是Linux系统中用户空间的第一个进程,在Android中,它也是Android用户空间的第一个进程,它的进程号是1,。作为天子第一号进程,init被赋予了很多及其重要的职责。

咋们再看一看adb中的进程信息:
这里写图片描述
这里写图片描述

着重看一下PID PPID,已经用红线框圈出来了,init是第一个进程,它的子进程包括:zygote 、system/bin/* 等。
以上可以看出init在Android启动过程中的作用。
跟踪源码 system/core/init/init.c
main方法如下,代码有点长:

int main(int argc, char **argv)
{
    int fd_count = 0;
    struct pollfd ufds[4];
    char *tmpdev;
    char* debuggable;
    char tmp[32];
    int property_set_fd_init = 0;
    int signal_fd_init = 0;
    int keychord_fd_init = 0;
    bool is_charger = false;

    char* args_swapon[2];
    args_swapon[0] = "swapon_all";;
    args_swapon[1] = "/fstab.sun8i";;

    char* args_write[3];
    args_write[0] = "write";
    args_write[1] = "/proc/sys/vm/page-cluster";
    args_write[2] = "0";

    if (!strcmp(basename(argv[0]), "ueventd"))
        return ueventd_main(argc, argv);

    if (!strcmp(basename(argv[0]), "watchdogd"))
        return watchdogd_main(argc, argv);

    /* clear the umask */
    umask(0);

        /* Get the basic filesystem setup we need put
         * together in the initramdisk on / and then we'll
         * let the rc file figure out the rest.

         //创建一些Linux系统根文件系统的目录
         */
    mkdir("/dev", 0755);
    mkdir("/proc", 0755);
    mkdir("/sys", 0755);
    mount("tmpfs", "/dev", "tmpfs", MS_NOSUID, "mode=0755");
    mkdir("/dev/pts", 0755);
    mkdir("/dev/socket", 0755);
    mount("devpts", "/dev/pts", "devpts", 0, NULL);
    mount("proc", "/proc", "proc", 0, NULL);
    mount("sysfs", "/sys", "sysfs", 0, NULL);

        /* indicate that booting is in progress to background fw loaders, etc */
    close(open("/dev/.booting", O_WRONLY | O_CREAT, 0000));

        /* We must have some place other than / to create the
         * device nodes for kmsg and null, otherwise we won't
         * be able to remount / read-only later on.
         * Now that tmpfs is mounted on /dev, we can actually
         * talk to the outside world.
         */
    open_devnull_stdio();
    klog_init();            //初始化log,写入init进程信息
    property_init();

    get_hardware_name(hardware, &revision);    // 取得硬件名


    process_kernel_cmdline();

    union selinux_callback cb;
    cb.func_log = klog_write;
    selinux_set_callback(SELINUX_CB_LOG, cb);

    cb.func_audit = audit_callback;
    selinux_set_callback(SELINUX_CB_AUDIT, cb);

    selinux_initialize();
    /* These directories were necessarily created before initial policy load
     * and therefore need their security context restored to the proper value.
     * This must happen before /dev is populated by ueventd.
     */
    restorecon("/dev");
    restorecon("/dev/socket");
    restorecon("/dev/__properties__");
    restorecon_recursive("/sys");

    is_charger = !strcmp(bootmode, "charger");
    usb_charge_flag = is_charger;

    INFO("property init\n");
    if (!is_charger)
        property_load_boot_defaults();
    get_kernel_cmdline_partitions();
    get_kernel_cmdline_signature();
    INFO("reading config file\n");
    init_parse_config_file("/init.rc");   //读取并且解析init.rc文件

    action_for_each_trigger("early-init", action_add_queue_tail);//触发在init脚本文件中名字为early-init的action,并且执行其commands,其实是: on early-init

    queue_builtin_action(wait_for_coldboot_done_action, "wait_for_coldboot_done");
    queue_builtin_action(mix_hwrng_into_linux_rng_action, "mix_hwrng_into_linux_rng");
    queue_builtin_action(keychord_init_action, "keychord_init");

    /* execute all the boot actions to get us started */
    action_for_each_trigger("init", action_add_queue_tail);     //触发在init脚本文件中名字为init的action,并且执行其commands,其实是:on init

    action_for_each_trigger("early-fs", action_add_queue_tail);
    /* skip mounting filesystems in charger mode */
    if (!is_charger) {
        queue_builtin_action(console_init_action, "console_init");
        action_for_each_trigger("fs", action_add_queue_tail);
        action_for_each_trigger("post-fs", action_add_queue_tail);
        action_for_each_trigger("post-fs-data", action_add_queue_tail);

        //SWAP TO ZRAM if low mem devices
        if (!(get_dram_size() > 512)) {
            char trigger[] = {"early-fs"};
            ERROR("***************************LOW MEM DEVICE DETECT");
            add_command(trigger, 2, args_swapon);
            char trigger2[] = {"post-fs-data"};
            add_command(trigger2, 3, args_write);
        }
    }

    /* Repeat mix_hwrng_into_linux_rng in case /dev/hw_random or /dev/random
     * wasn't ready immediately after wait_for_coldboot_done
     */
    queue_builtin_action(mix_hwrng_into_linux_rng_action, "mix_hwrng_into_linux_rng");

    queue_builtin_action(property_service_init_action, "property_service_init");
    queue_builtin_action(signal_init_action, "signal_init");
    queue_builtin_action(check_startup_action, "check_startup");

    if (is_charger) {
        queue_builtin_action(console_init_action, "console_init");
        action_for_each_trigger("charger", action_add_queue_tail);
    } else {
        action_for_each_trigger("early-boot", action_add_queue_tail);
        action_for_each_trigger("boot", action_add_queue_tail);
    }

        /* run all property triggers based on current state of the properties
         启动所有属性变化触发命令,其实是: on property:ro.xx.xx=xx
        */
    queue_builtin_action(queue_property_triggers_action, "queue_property_triggers");


#if BOOTCHART
    queue_builtin_action(bootchart_init_action, "bootchart_init");
#endif

    for(;;) {
        int nr, i, timeout = -1;

        execute_one_command();
        restart_processes();    //重启那些已经死去的进程


 -- -- --  --
//调用poll 等待一些事情的发生
        nr = poll(ufds, fd_count, timeout); 
        if (nr <= 0)
            continue;

        for (i = 0; i < fd_count; i++) {
            if (ufds[i].revents & POLLIN) {
                if (ufds[i].fd == get_property_set_fd())
                    handle_property_set_fd();
                else if (ufds[i].fd == get_keychord_fd())
                    handle_keychord();
                else if (ufds[i].fd == get_signal_fd())
                    handle_signal();
            }
        }
    }

    return 0;
}

上面解析中英文标注和对照文中首先提出来的Android启动流程图,看看Init进程究竟做了什么,主要做了一下四个方面:

  • 解析两个配置文件,其中最总要的就是init.rc文件
  • 执行各个阶段动作,这些动作是在解析完init.rc文件后产生的action【zygote就是其中一个】
  • 调用property_init初始化属性相关资源,并且通过property_start_service启动属性服务
  • init进入无限循环,并且等待一些事情的发生。重点是处理来自socket和属性服务器的相关事情

参考:

深入理解Android:卷I》是一本以情景方式对Android的源代码进行深入分析的书。内容广泛,以对Framework层的分析为主,兼顾Native层和Application层;分析深入,每一部分源代码的分析都力求透彻;针对性强,注重实际应用开发需求,书所涵盖的知识点都是Android应用开发者和系统开发者需要重点掌握的。 全书共10章,第1章介绍了阅读本书所需要做的准备工作,主要包括对Android系统架构和源码阅读方法的介绍;第2章通过对Android系统的MediaScanner进行分析,详细讲解了Android十分重要的JNI技术;第3章分析了init进程,揭示了通过解析init.rc来启动Zygote以及属性服务的工作原理;第4章分析了Zygote、SystemServer等进程的工作机制,同时还讨论了Android的启动速度、虚拟机HeapSize的大小调整、Watchdog工作原理等问题;第5章讲解了Android系统常用的类,包括sp、wp、RefBase、Thread等类,同步类,以及Java的Handler类和Looper类,掌握这些类的知识后方能在后续的代码分析做到游刃有余;第6章以MediaServer为切入点,对Android极为重要的Binder进行了较为全面的分析,深刻揭示了其本质。第7章对Audio系统进行了深入的分析,尤其是AudioTrack、AudioFlinger和AudioPolicyService等的工作原理。第8章深入讲解了Surface系统的实现原理,分析了Surface与Activity之间以及Surface与SurfaceFlinger之间的关系、SurfaceFlinger的工作原理、Surface系统的帧数据传输以及LayerBuffer的工作流程。第9章对Vold和Rild的原理和机制进行了深入的分析,同时还探讨了Phone设计优化的问题;第10章分析了多媒体系统MediaScanner的工作原理。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ItJavawfc

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值