Android系统启动流程总览

来源:互联网 发布:电脑钢琴学习软件 编辑:程序博客网 时间:2024/05/29 15:43

绪论

    Android是基于Linux内核的, 可扩展的智能终端设备. 越来越多的用户使用Android设备, 而移动智能时代已经悄然而至,很多人都感觉这是一个神奇的世界, 对其知之甚少. 就让我们通过本文来揭开Android设备系统启动的神秘面纱,以此来了解这个神秘的世界.

Android系统总览

   当电源键按下,引导芯片代码开始从预定义的地方(固化在ROM)开始执行,加载引导程序到RAM,然后执行。
引导程序是Android操作系统开始运行前的一个小程序,一般使用bootloader作为引导程序。引导程序分为两个阶段执行:
1)检测外部的RAM以及加载对第二阶段有用的程序。
2)引导程序设置网络,内存等等。
引导程序可以根据配置参数或输入数据进行配置内核,并且进行加载内核。
    内核启动时会进行设置缓存,被保护存储器,计划列表,加载驱动。当内核完成系统设置后,它首先在系统文件中寻找init文件,然后启动init进程。
    Init进程是Linux起来之后启动的第一个用户进程,android系统就是在这个进程的基础上启动起来的,进程号为1,init进程主要就是挂载文件目录,如sys/,dev/,proc/。另外就是运行init.rc脚本。由于在init.rc中有对启动Zygote的参数配置,所以最终可以将Zygote启动起来。
    Zygote是一个孵化器进程,所有的应用程序进程以及系统服务进程SystemServer都是由Zygote进程孕育fork出来的。在Zygote中进行添加虚拟机参数,并将其启动起来,然后注册JNI函数。在Zygote中进行预加载以及初始化核心类库。最后将SystemServer启动起来。
    在SystemServer中进行对各种系统服务对象进行创建,并将创建好的对象,添加进SeviceManager中可以让其他模块通过ServiceManager就可以获得所需要的服务对象。
    前面所有事情都完成后,就可以进行启动Launcher了,最终出现系统主界面。

主要内容

  1. uboot启动流程
  2. uboot调试方法
  3. kernel启动流程
  4. kernel编译调试方法
  5. 概述init到启动Launcher过程

uboot启动流程

u-boot启动过程可以分为两个阶段,两个阶段的功能如下:

第一阶段的功能

1.硬件设备初始化
2.加载uboot第二阶段代码到RAM空间
3.设置好栈   
4.跳转到第二阶段代码入口

第一阶段对应的文件是u-boot64/arch/arm/cpu/Armv7/start.S。u-boot启动第一阶段流程如下:

                                                    

第二阶段的功能

1.初始化本阶段使用的硬件设备
2.检测系统的内存映射
3.将内核从Flash读取到RAM中  
4.为内核设置启动参数  
5.调用内核

u-boot第二阶段代码的入口为board_init_r()函数,在u-boot/arch/arm/lib/board.c中定义。U-boot启动第二阶段流程如下:
                                                         

board_init_r()是第二阶段C语言开始的函数,该函数主要是调用一系列的初始化函数,初始化高速缓存器和本阶段的外围硬件设备。
之后,跳到do_cboot()函数:
  1. 判断开机模式
  2. 进入相应的开机模式
  3. 点亮屏幕
  4. 显示厂商开机logo界面
> 将内核映像和跟文件映像从flash上读到SDRAM空间中
> 为内核设置启动参数
> 启动内核

Uboot调试方法

可以通过仿照uboot中原有log的格式进行添加log调试,通过minicom抓取串口log.
> 使用minicom获取串口log方法:
  1. >安装:sudo apt-get install minicom
  2. >配置:sudo minicom -s
  3. >设置端口:Serial port setup
        
串口端口号一般为ttyUSB1或者ttyUSB0
设置完成后就可以进入minicom,进行抓取串口log,调试uboot.

启动内核

在U-boot中对内核进行设置启动参数,经过一系列的跳转,最终到了start_kernel()进行启动kernel.代码位置kernel/init/main.c

                                                                             
当以上所有的初始化工作结束后,start_kernel()函数会调用 rest_init()函数来进行最后的初始化,包括启动系统的第一个进程-init进程来结束内核的启动。在rest_init函数中调用kernel_init来进行接下来的初始化.
                                                                       


Kernel编译与调试

编译kernel其实就是编译boot.img, boot.img是由ramdisk.img和kernel打包组成.ramdisk中包含一些对于启动android的很重要的文件,比如内核启动完后,加载的第一个进程init,一些重要的配置文件(如init.rc)等,总之它控制着整个android的启动
> 编译命令:make bootimage
编译完成后可以用fastboot将boot.img烧到手机中:
  1. adb reboot bootloader
  2. fastboot flash boot .../boot.img
  3. fastboot reboot
有时候由于kernel的缓冲buffer不够大, 在开机过程中可能会冲掉一部分kernel log,导致kernel log不全为分析开机耗时问题带来不小的困恼. 所以,我们在调试的时候可以适当的增大kerne buffer size, 在源码根目录执行kuconfig, 显示如下界面:

                                           

> 选择General Setup选项
                         
我们就可以选择kernel log buffer size选项, 17为128KB , kernel log buffer最大为21, 所以我们可以将17改为小于等于21的一个数值. 这样就可以输出比较多的kernel log信息.
                            


在内核 printk.h 文件中定义了很多内核打印 Log 的级别和方法,最常用的就是直接使用
printk(“++++++++++++++++++++++++\n”)
使用dump_stack()输出堆栈信息.

启动Init进程

在kernel中启动Init进程完成后,正式进入用户空间init进程也为用户空间的第一个进程,之后会进入system/core/init/init.cpp中的main()函数,首先将在启动kernel过程中创建好的文件系统框架mount到相应目录,之后对init.rc文件进行解析.

                                                                                  

启动zygote

[java] view plain copy
  1. //system/core/rootdir/init.zygote64.rc  
  2. service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server  
  3.     class main  
  4.     socket zygote stream 660 root system  
  5.     onrestart write /sys/android_power/request_state wake  
  6.     onrestart write /sys/power/state on  
  7.     onrestart restart media  
  8.     onrestart restart netd  
根据zygote的path name可以知道Zygote进程是通过system/bin/app_process64启动的,之后会进入app_main.cpp的main函数,最后启动zygote
          

在app_main.cpp的main函数主要通过启动zygote的参数来对虚拟机进行设置.
间接调用AndroidRuntime的start函数
  1. 启动虚拟机
  2. 对虚拟机进行一些初始化
  3. 注册JNI函数
最后调用ZygoteInit的main函数,进入java层.

进入java世界

                                      
在java层经过一系列操作最终将launcher启动起来, 我们就可以操作app,尽情的玩耍了。
后续文章中将详细讲解用户空间的调用,以及开机优化的点子。
原创粉丝点击