Android源码--开机启动流程学习

目录

Android源码

下载

目录结构

编译

android启动流程

第一阶段:Linux内核启动

第二阶段:Android Framework启动

第二, 解析启动脚本文件 init.rc;

第三,根据启动脚本 init.rc 的解析结果开启 Android Framework 核心服务进程;

第三阶段:应用程序 Launcher启动


 

Android源码

下载

2018-2-4

直接使用清华大学的镜像【注意不能使用VMware + Ubuntu + 共享文件夹的方式,主要英文共享文件夹不支持linux某些文件】

https://mirrors.tuna.tsinghua.edu.cn/help/AOSP/

 

目录结构

2018-2-5

http://blog.csdn.net/itachi85/article/details/54695046

详细目录结构

http://blog.csdn.net/ieearth/article/details/64930164

 

编译

从网上下载的android源码不包括u-boot和linux内核,需要下载对应的版本,然后在编译。

 

android启动流程

在学习启动流程时,首先打印Android的启动日志,打印方法参见:Android内核开发:如何统计系统的启动时间,如果要分析内核启动流程,一定要打印出日志,比如从下面日志可以看出,内核启动时间为2.8秒:

Android源码--开机启动流程学习_第1张图片

先贴一张图:

Android源码--开机启动流程学习_第2张图片

2018-2-6

Android 的底层基于 Linux Kernel,因此从启动流程来看,先启动 Linux Kernel,然后才启动 Android Framework,最后进入应用程序 Launcher,也就是看到的主界面。因此可将Android的启动流程分为下面3个阶段:

 

第一阶段:Linux内核启动

主要参考:Android笔记 - Android启动之Linux内核启动

这一阶段有分为三个过程:

(1)机器上电,进入Bootrom

Bootrom 是固化在芯片中的一小段程序,主要功能是上电时完成硬件自检,然后从固定分区加载 Bootloader。Bootrom 的功能相当于 PC 上的 BIOS,Bootloader 的功能相当于 PC 上的 GRUB。这个程序一般是硬件厂商做的,Android手机厂商不会修改。

(2)Bootloader初始化软硬件环境 ,

Bootloader 是在进入 Linux Kernel 之前运行的程序。Android 采用的 Bootloader 实现方式是 Uboot。手机厂商一般会定制化Bootloader程序,这程序的主要作用是检测硬件,加载linux kernel。

(3)启动 Linux Kernel ,

这一阶段和标准 Linux Kernel 启动过程基本一致。Kernel 加载进内存后会进行自解压。自解压完成后,继续进行一些平台相关的初始化,然后开始 start_kernel 函数,它的实现代码位于 init/main.c 中。

Android源码--开机启动流程学习_第3张图片

以上分析基于 linux-4.4.52内核,至此,linux内核分析完毕。这里的“/init”进程是用户空间中的额第一个进程。

引导程序之后进入Android内核层,先启动swapper进程(idle进程),该进程用来初始化进程管理、内存管理、加载Display、Camera Driver、Binder Driver等相关工作。
swapper进程之后再启动kthreadd进程,该进程会创建内核工作线程kworkder、软中断线程ksoftirqd、thernal等内核守护进程,kthreadd进程是所有内核进程的鼻祖

“/init”进程是所有用户进程的鼻祖。init进程是所有用户进程的鼻祖,它会接着孵化出ueventd、logd、healthd、installd、adbd、lmkd等用户守护进程,启动ServiceManager来管理系统 服务,启动Bootnaim开机动画。
init进程通过解析init.rc文件fork生成Zygote进程,该进程是Android系统第一个Java进程,它是所有Java进程父进程,该进程主要完成了加载ZygoteInit类,注册Zygote Socket 服务套接字;加载虚拟机;预加载Class;预加载Resources。
 

备注:我们知道,linux内核的系统有固定的流程,一般内核启动完毕后,就是加载用户的程序,用户的程序一般放在某个脚本中(好像是“/etc/init/init.rc”文件),执行脚本中的每一行语句,即开启相应的进程。

(备注,这里想查看Android系统运行的信息,可以启动Android Studio的模拟器,这个模拟器运行起来后,是有root权限的,这样在查看信息时,就很方便了)

以下是天嵌TQ2440的打印信息(linux-2.6.30版本),可供参考:

Android源码--开机启动流程学习_第4张图片

Android源码--开机启动流程学习_第5张图片

由以上分析,Android的系统,应该是linux的内核启动完成后,再启动必要的进程,最后通过脚步文件启动Android的程序。

参考:Android的init过程详解(一)

 

第二阶段:Android Framework启动

2018-2-7

init 进程(PID=1,用户空间的第一个进程,也是Android系统的第一个进程)进入 main 函数后,主要完成以下四项工作。第一,在根文件系统中创建目录作为挂载点,然后挂载虚拟文件系统;第二, 解析启动脚本文件 init.rc;第三,根据启动脚本 init.rc 的解析结果开启 Android Framework 核心服务进程;第四,监听事件,重启服务。

上面说的init进程(进程名为“/init”,PID=1,根目录下的init可执行文件),是由android源码(Android-7.1版本)中的/system/core/init/init.cpp文件编译出来的,这个进程名为“/init”的进程会执行根目录下的 init.*.rc 脚步(具体的执行规则,参见:Android的init过程(二):初始化语言(init.rc)解析),这个脚步是负责启动Android framework的(见:Android笔记 - Android启动之Android Framework启动)。

为了学习AIL(Android初始化语言,Android Init Language,这里简称为AIL),读者可以到自己Android手机的根目录寻找init.rc文件,最好下载到本地以便查看,如果有编译好的Android源代码,在out/target/product/generic/root目录也可找到init.rc文件。

第二步和第三步最重要,这个过程中会启动系统所需功能的各种服务。主要分为本地服务和Android服务,它们都会在ServiceManager中进行注册。

本地服务 
本地服务是指运行在C++层的系统守护进程,一部分本地服务是init进程直接启动的,它们定义在init.rc脚本和init..rc中,如 ueventd、servicemanager、debuggerd、rild、mediaserver等。还有一部分本地服务,是由这些本地服务进一步创建的,如mediaserver服务会启动AudioFlinger, MediaPlayerService, 以及 CameraService 等本地服务。我们可以通过查看init.rc和init..rc文件找出具体有哪些本地服务被init进程直接启动了,这些文件的位置:system/core/rootdir/

Android服务 
Android服务是指运行在Dalvik虚拟机进程中的服务,这些服务的创建过程描述如下:
init进程会执行app_process程序,创建Zygote进程,它是Android系统最重要的进程,后续所有的Android应用程序都是由它fork出来的。 
Zygote进程会先fork出SystemServer进程,SystemServer进程就会启动所有的Android核心服务。例如:Activity Manager、Window Manager、Power Manager等等服务。当所服务启动完毕后,SystemServer会打印出”Making services ready”,然后通过Activity Manager启动Home界面,并发送“ACTION_BOOT_COMPLETED”广播消息。 
SystemServer进程添加的服务都属于SystemServer进程。

Android服务是指运行在Dalvik虚拟机进程中的服务,这些服务的创建过程描述如下:

init进程会执行app_process程序,创建Zygote进程,它是Android系统最重要的进程,所有后续的Android应用程序都是由它fork出来的。

 

第二, 解析启动脚本文件 init.rc;

init 可执行文件的代码(/system/core/init/init.cpp)的main函数中解析“/init.rc”脚步,源码:

int main(int argc, char** argv) {

.......

    Parser& parser = Parser::GetInstance();
    parser.AddSectionParser("service",std::make_unique());
    parser.AddSectionParser("on", std::make_unique());
    parser.AddSectionParser("import", std::make_unique());
    parser.ParseConfig("/init.rc");
.......
}

解析 init.rc 的工作由函数 Parser 来完成。解析完成后,得到一个 service_list 链表和一个 action_list 链表。其中,service_list 链表用来保存 service 的解析结果,action_list 链表用来保存 action 的解析结果。如下图所示: 

Android源码--开机启动流程学习_第6张图片

为了让 action 按照一定的顺序触发,需要对 action 在链表中的顺序进行调整,调整后的 action 由 action_queue 链表来保存。

第三,根据启动脚本 init.rc 的解析结果开启 Android Framework 核心服务进程;

通过之前的初始化工作得到 action_queue 链表后,调用 execute_one_command 函数遍历 action_queue 链表,并执行链表中 action 的 command。

在这些启动的核心服务进程中,其中两个最重要的核心服务进程是 servicemanager 进程和zygote 进程。

servicemanager 进程是 Binder 进程间通信机制的核心之一。它负责管理系统中所有的 Service 组件,提供 Service 组件的注册服务,并且向 Client 组件提供获取 Service 代理对象的服务。

zygote 进程是 Android 启动后的第一个虚拟机进程。它主要负责启动 system_server 进程,以及所有的应用程序进程,所以也称为孵化器进程。zygote 进程会启动子进程 system_server,system_server 进程在 nativeInit 函数中启动 Native 系统服务比如 SensorService,在 ServerThread 的 initAndLoop 函数中启动 Java 系统服务比如 ActivityManagerService, PackageManagerService, ContentService 等,并将系统服务注册进 ServiceManager。

ServiceManager

init进程启动后,ServiceManager进程的启动,远比zygote要早,因为在启动zygote进程时需要用到ServiceManager进程的服务。ServiceManager是一个守护进程,它维护着系统服务和客户端的binder通信。

从内核的启动日志可以看出,ServiceManager要比zygote要早:

ServiceManagerde启动脚本在Android6.0以前的版本(包括6.0)中放在 init.rc文件中,如:

//Android 6.0版本,在/init.rc
service servicemanager /system/bin/servicemanager
    class core
    user system
    group system
    critical
    onrestart restart healthd
    onrestart restart zygote
    onrestart restart media
    onrestart restart surfaceflinger
onrestart restart drm

在Android7.0版本中放在 /system/etc/init/servicemanager.rc 文件中,如:

Android源码--开机启动流程学习_第7张图片

这里,系统是如何一步步启动/system/etc/init/servicemanager.rc脚本的,我不知道(没找到对应的源代码),只是从日志分析得出,系统有解析/system/etc/init/servicemanager.rc文件,如:

该进程对应的源码路径为:frameworks/native/cmds/servicemanager/service_manager.c。

分析源码,发现就是开启bindler机制,对应的源码如下:

//  frameworks/native/cmds/servicemanager/service_manager.c
int main()
{
    struct binder_state *bs;

    bs = binder_open(128*1024);
    if (!bs) {
        ALOGE("failed to open binder driver\n");
        return -1;
    }

    if (binder_become_context_manager(bs)) {
        ALOGE("cannot become context manager (%s)\n", strerror(errno));
        return -1;
    }

    selinux_enabled = is_selinux_enabled();
    sehandle = selinux_android_service_context_handle();
    selinux_status_open(true);

    if (selinux_enabled > 0) {
        if (sehandle == NULL) {
            ALOGE("SELinux: Failed to acquire sehandle. Aborting.\n");
            abort();
        }

        if (getcon(&service_manager_context) != 0) {
            ALOGE("SELinux: Failed to acquire service_manager context. Aborting.\n");
            abort();
        }
    }

    union selinux_callback cb;
    cb.func_audit = audit_callback;
    selinux_set_callback(SELINUX_CB_AUDIT, cb);
    cb.func_log = selinux_log_callback;
    selinux_set_callback(SELINUX_CB_LOG, cb);

    binder_loop(bs, svcmgr_handler);

    return 0;
}

 

 

zygote】进程

Android 7.0 版本的zygote进程有两个:

早期Android版本(4.4以前)的zygote进程的启动脚本在init.rc文件中,之后的版本分32和64,Android 7.0 版本在 init.zygote64.rc 中的内容如下:

//android_source\system\core\rootdir\init.zygote64_32.rc
service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server --socket-name=zygote
    class main
    socket zygote stream 660 root system
    onrestart write /sys/android_power/request_state wake
    onrestart write /sys/power/state on
    onrestart restart audioserver
    onrestart restart cameraserver
    onrestart restart media
    onrestart restart netd
    writepid /dev/cpuset/foreground/tasks

service zygote_secondary /system/bin/app_process32 -Xzygote /system/bin --zygote --socket-name=zygote_secondary
    class main
    socket zygote_secondary stream 660 root system
    onrestart restart zygote
    writepid /dev/cpuset/foreground/tasks

根据 Android 初始化语言的语法,可以知道 zygote 服务进程的名字是 zygote ,执行程序路径为 /system/bin/app_process64,参数为-Xzygote /system/bin --zygote --start-system-server --socket-name=zygote。参数“--zygote”的表当前进程用于承载zygote,参数“--start-system-server”表示启动“system_server”进程。“socket zygote stream 660 root system”表示创建一个名字为 zygote 的 socket,这个 socket 用于接收 ActivityManagerService 发送过来的新建应用程序进程的请求。zygote 进程重启时会往 sysfs 中写入命令,同时会重启 audioserver、cameraserver、media 和 netd 服务。

详细看林学森的《深入理解Android内核设计思想》,该部分的讲解是4.4版本以后的。

该进程对应Android中的源码在:frameworks/native/cmds/app_process/app_main.c。具体启动细节请参考老罗的文章 Android 系统进程 Zygote 启动过程的源代码分析。

Zygote进程会首先fork出"system_server"进程,"system_server"进程的全部任务就是将所有的Android核心服务启动起来,这些服务包括:

Android源码--开机启动流程学习_第8张图片

喜欢以图的方式呈现,代码分析如下图,(代码版本7.0):

Android源码--开机启动流程学习_第9张图片

zygoteInit函数很关键,如下:

Android源码--开机启动流程学习_第10张图片

在以上的分析中,可以看到所有由SystemServer.java 文件中run()函数启动的 Service 都统一由 SystemServiceManager 来管理。

 

 

 

第三阶段:应用程序 Launcher启动

也就是最终会看到的 Android 桌面的启动。

 

 

http://blog.csdn.net/yanshazi/article/details/50287479

 

 

 

 

 

 

 

你可能感兴趣的:(Android源码学习)