新手大战Android源码之启动过程

新手上路,当学习笔记整理记忆。
先来个基本启动流程框架图:
简要图

1 招兵买马

古语云:机会总是留给有准备的人。为了这场战役,我准备了如下几个利器。

  • 深入理解Android卷I书籍一本
  • 有关博客数篇,大小不限,高矮胖瘦都不限。
  • 可以随时百度的百度。
    本新手一个,所以实力有限,招兵买马也仅限于此。实在是难登大雅之堂。

2 打探敌情

战不得不战,打非得打。但也不能蛮打不是,蛮打多么没素质,没品位呢。得智取。于是乎,了解一下对方的实力吧。
敌手实力不容小视,单单一个Android系统启动流程就屯兵百万。
瞎话就不叙述了,进入正题,据探子回报:

  1. 底层linux kernel
    Android源代码于底层linux搭边的在System\core…里。而存放各种待解析的文件则在System\core\rootdir里面。比如init.rc,uevent.rc,init.zygote32.rc等,以rc为文件后缀存放的,类似于编译原理的各种规定的语法格式,以便后面文件进行解析。

  2. 次底层的libraries以及Android Runtime的Dalvik 虚拟机
    这里面包含了引用库。一般都存放在模块的子目录里。
    主要包含C语言和JNI等编写的程序。

  3. 次顶层的Application Framework
    是各种服务的管理者,activity manager,resource manager,view System等。主要存在于framwork\base\里。包含Java语言,c++语言,以及native的JNI。

  4. 顶层的Application
    这个就不多说了,各种api,各种服务都给你准备好了,只等调用了。
    本次关于启动的研究,没深入敌营到如此深的地步,止步于次底层。

3 大战开始

本想从别的地方找找开打的地方,但是基于程序员的潜意识,总觉得init是个梦开始的地方。哈哈。那就从这研究吧。

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;

    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.
         */
    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));

    ...........
   .............
    INFO("reading config file\n");
    init_parse_config_file("/init.rc");

    action_for_each_trigger("early-init", action_add_queue_tail);


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

        execute_one_command();
        restart_processes();

        if (!property_set_fd_init && get_property_set_fd() > 0) {
            ufds[fd_count].fd = get_property_set_fd();
            ufds[fd_count].events = POLLIN;
            ufds[fd_count].revents = 0;
            fd_count++;
            property_set_fd_init = 1;
        }
              if (process_needs_restart) {
            timeout = (process_needs_restart - gettime()) * 1000;
            if (timeout < 0)
                timeout = 0;
        }

        if (!action_queue_empty() || cur_action)
            timeout = 0;

#if BOOTCHART
        if (bootchart_count > 0) {
            if (timeout < 0 || timeout > BOOTCHART_POLLING_MS)
                timeout = BOOTCHART_POLLING_MS;
            if (bootchart_step() < 0 || --bootchart_count == 0) {
                bootchart_finish();
                bootchart_count = 0;
            }
        }
#endif

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

单单一个main函数就又高又壮,看的头都大了。那就umask(0)为何是权限最大值,请查阅相关资料,这给个链接啊http://zhidao.baidu.com/link?url=EM6Z49OctQaxCVa38HloyfgpnIqVguMRWRW7T16dt3njaY1ykN4UlkFGHli-PJnTYfFmR51WjrtS9ImAr4f7Z
Pc_)。然后不能浪费上面给的权力啊,因此会执行各种目录的建立,挂载,关于init.rc的解析,解析后会产生响应的属性配置list表,进行属配置,配置后启动相应的service_list,这里会启动zygo后面就会属性启动,例如:来大麻烦。最后不断的检测和重启挂掉的服务。对于service的结构体的定义书《深入理解Android》有介绍,里面各种属性被赋值,各种服务所携带的属性值也就不同了,后面就会属性启动,例如:zygote的svc(为service的结构体)svc->classname为default属性。解决掉init的main函数之后,再去找找附带的喽喽兵看看。
来到init.rc的文件下,看看所谓的用规定语法格式进行指令书写的文件的是什么样。截图如下:init.rc的部分截图
注意到了没,以on和service的关键字的前面没有缩进啊,说明这两个是要存在什么问题的,查看keyword.h的里面的宏定义,发现对应SECTION,同时还存在其它几种,opinion和command。这样解析的时候就会差别对待。

4 乘胜追击

对于初始化起来的各项服务有很多,除了基本的内核通信之类的服务之外,哪个服务是给后期Android启动铺路的呢?这需要研究研究。在init.zygote32_64.rc的文件中,发现了这个。
init.zygote32_64.rc截图
里面有Android_power以及power state on。入口是这啊。且慢,最上面一行的又是啥东东?system\bin下面的app_process32 和后面的start system_server…..socket-name = zygote?
实际上,深入浅出Android书里已说明,zygote本身是一个native的应用程序,和驱动以及内核没有关系。从上面的指令中我们也看到system\bin\app_process32。也就是zygote的另一个名字。
接下来转入到zygote的初始化,转到路径framework\base\core\java\com\android\internal\os\zygoteinit.java.看到了如下的东东。
main函数
开始要进行Dalvik虚拟机框架启动的简要框架集成的初始化,随后对main函数的其他属性值进行检查赋值操作。图中圈大圈的部分。然后注册socket套接字,书写系统事件日志。为Dalvik虚拟机进行简要的框架环境注册之后,要进行预加载各种资源以及类,书中说要加载的类多大1200多个,时代在进步,目前已经有3000多个类要预先加载。使用gc进行建议性的回收,因为Java的回收我们是没有办法进行精准的控制。这样做的目的也是对之前预加载后进行空间上的资源释放。启动system server。runSelectLoop。关闭socket。会有疑惑,怎么关闭了socket了,难道zygote命要终结了?其实不是,在关闭之前,runselectloop被调用,里面是while(true){}。会不断响应其他请求。
对于system server启动,涉及好多服务类,以及对各个服务的守护,今天时间有限,改日了解记录。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值