当我们按下电源键,Android 究竟做了些什么?

44次阅读

共计 3724 个字符,预计需要花费 10 分钟才能阅读完成。

欢迎大家前往腾讯云 + 社区,获取更多腾讯海量技术实践干货哦~
本文由 goo 发表于云 + 社区专栏相信我们对 Android 系统都不陌生,而 Android 系统博大精深,被各种各样的智能设备承载的同时,我们会否好奇过,如此复杂的 Android 究竟是怎么运作起来的呢?借本文给大家分享,笔者对 Android 系统启动流程的整体理解~

hi, I’m Android
现在,按下电源键
下面是 Android 启动的核心步骤流程图,看文字的时候,记得回来对照图来理解喔,希望阅读全文后,回观流程图,会有恍然大悟的感觉,那么文章的目的就达到啦~
整体流程
一、启动电源及系统启动
系统从 ROM 中开始启动,加载引导程序到 RAM,然后执行。
二、引导程序
引导程序是 Android 操作系统开始运行前的一个小程序,因此它需要针对特定主板与芯片,并不是 Android 操作系统的一部分。引导程序是 OEM 厂商或运行商进行加锁、限制的地方。
1 两个阶段

检测外部 RAM 以及为第二阶段加载程序
设置网络、内存等,搭建内核运行环境(为了达到特殊目的时,引导程序可以根据配置参数或者输入数据来设置内核)

2 引导程序的加载器
Android 引导程序可以在 bootablebootloaderlegacyusbloader 找到,传统的加载器包含的两个文件:

init.s 初始化堆栈,清零 BSS 段,会调用 main.c 中的 _main() 函数(bss segment:通常是指用来存放程序中未初始化的全局变量的一块内存区域;BSS – Block Started by Symbol。BSS 段属于静态内存分配)
main.c 初始化硬件,创建 linux 标签

三、内核启动
Android 内核启动方式类似桌面 linux,主要步骤:
1. 设置缓存
2. 被保护存储器
3. 计划列表
4. 加载驱动
当内核完成系统设置,接下来即将启动系统的第一个进程 — init 进程
四、init 进程
作为 Android 系统的第一个进程,其 PID 为 0,通过解析 init.rc 脚本来构建出系统初始运行形态,这一阶段中,“Android”logo 会显示出来
(系统中,大多数系统服务程序都是在该脚本中描述并被相继启动的)
init.rc 由 4 种类型声明组成:Actions、Commands、Services、Options

Actions:响应某事件的过程。当“trigger”所描述的触发事件产生时,则依次执行各种“command”源码角度:系统会对 init.rc 中各“trigger”进行匹配,当发现符合条件的 Action,就将它加入“命令执行队列”尾部(除非 Action 已存在队列中),然后系统再对这些命令按顺序进行。on <trigger> ## 触发条件 <command1> ## 执行命令 <command2> ## 可执行多个命令 …

Commands:命令将在所属事件发生时被一个个执行

Services:可执行程序,它们在特定选项的约束下会被 init 程序运行或者重启(Service 可以在配置中指定是否需要退出重启,那么,当 Service 出现异常 crash 时,可有机会复原)service <name><pathname> [<argument>]* <option> <option>

Options: 对 service 的约束选项

五和六、ServiceManager、Zygote、SystemServer
科普:Daemons – 守护进程
init 进程通过解析 init.rc 来陆续启动其他关键的系统服务进程,其中最重要的是 ServiceManager、Zygote 和 SystemServer 三者,下面我们逐一解析:
1 ServiceManager — Binder 机制支撑者
概述:ServiceManager 是 Binder 机制中的支撑者,负责某 Binder 服务注册信息到底层 Binder 驱动分配的值解析。
ServiceManager 由 init 进程解析 rc 脚本时启动,属于 core 类,其他同类进程包括:uenetd、console、adbd 等。根据 core 组的特性,这些进程会同时启动或停止。另外,ServiceManager 配置含有 critical 属性,这意味着它是系统关键进程(如果进程不幸在 4 分钟内异常退出超过 4 次,设备将重启并进入还原模式)。当 ServiceManager 每次重启时,其他关键进程:zygote、media、surfaceflinger 等也会被 restart。
2. Zygote —“孕育”新线程与进程
Android 中大多数应用进程与系统进程都是通过 Zygote 来生成的。Zygote 同样由 init 解析 rc 脚本时启动,属于 main 类,同属 main 类的系统进程有:netd、debuggerd、rild 等。Zygote 并不是处于独立的程序中的,它所在程序名为“app_process”,观察 app_process 主函数实现知道,如果 init.rc 中指定了 –zygote 选项,app_process 接下来将启动“ZygoteInit”,并传入“start-system-server”, 这样,ZygoteInit 就会运行在虚拟机上(Dalvik VM)上了。

ZygoteInit 函数有两项重要工作
预装载各种系统类
搭建 SystemServer 环境,并启动 SystemServer(大部分的 Android 系统服务都在其中,由 Java 编写)

ZygoteInit 流程总结

摘自:Gityuan — Android 系统启动 -Zygote 篇

解析 init.zygote.rc 中的参数,创建 AppRuntime 并调用 AppRuntime.start() 方法;
调用 AndroidRuntime 的 startVM() 方法创建虚拟机,再调用 startReg() 注册 JNI 函数;
通过 JNI 方式调用 ZygoteInit.main(),第一次进入 Java 世界;
registerZygoteSocket() 建立 socket 通道,zygote 作为通信的服务端,用于响应客户端请求;
preload() 预加载通用类、drawable 和 color 资源、openGL 以及共享库以及 WebView,用于提高 ap 启动效率;
zygote 完毕大部分工作,接下来再通过 startSystemServer(),fork 得力帮手 system_server 进程,也是上层 framework 的运行载体。
zygote 功成身退,调用 runSelectLoop(),随时待命,当接收到请求创建新进程请求时立即唤醒并执行相应工作。

ZygoteInit 结束后,开机 Logo 就出来了。
(注意:这里并不包括开机动画,而是开机前“Android”Logo 出现的那个画面,开机动画出现之前还需要进行各种加载,开机动画是在“Android”Logo 出现之后才播放的)
3. SystemServer — 大部分 Android 系统服务所在地
SystemServer 是 Android 进入 Launcher 前的最后准备,它提供了众多的由“Java”语言编写的系统服务。
如果 init.rc 中为 zygote 指定启动参数 –start-system-server,那么 ZygotyeInit 就会调用 startSystemServer 来进入 SystemServer。

startSystemServer 函数解析:
首先 ZygoteInit 通过 Zygote.forkSystemServer 来生成一个新的线程(fork),用于承载各种系统服务。(源码角度:Zygote 内部由 Native 函数 Dalvik_dalvik_system_Zygote_forkSystemServer 来进一步实现,最终调用底层接口的 fork 接口来实际产生进程)
根据 fork 特性,子进程与父进程将获得相同的代码环境。pid 为 0 为子进程,否则为父进程;如果是前者,则进一步调用 handleSystemServerProcess(parseArgs) 函数来完成最核心的工作 —“启动各系统服务”(源码角度:handleSystemServerProcess 方法将 startSystemServer 中的 parsedArgs.remainingArgs 参数传给 RuntimeInit.zygoteInit,后者又调用 nativeZygoteInit 函数)
nativeZygoteInit 调用后,接着,三个重要的 static 函数就要被执行了:init1 – 完成本地 Service(SurfaceFlinger、AudioFlinger 等) 启动,完成后调用 init2、init2 – 新建一个新的带 Looper 的线程 ServerThread 来启动 Java 层各 Service

后语
上面对 Android 系统启动做了一个简述,意在给大家展现一个整体流程,其中每个环节涉及的知识点只是浅浅掠过,笔者也尚在学习与探索中,希望在后续再作详细分析。
资源推荐

Gityuan – Android 开篇
老罗的 Android 之旅
《深入理解 Android 内核设计思想》由浅入深,落实到源码层面上进行探索,知识很有深度

相关阅读【每日课程推荐】机器学习实战!快速入门在线广告业务及 CTR 相应知识

正文完
 0

当我们按下电源键,Android 究竟做了些什么?

44次阅读

共计 3724 个字符,预计需要花费 10 分钟才能阅读完成。

欢迎大家前往腾讯云 + 社区,获取更多腾讯海量技术实践干货哦~
本文由 goo 发表于云 + 社区专栏相信我们对 Android 系统都不陌生,而 Android 系统博大精深,被各种各样的智能设备承载的同时,我们会否好奇过,如此复杂的 Android 究竟是怎么运作起来的呢?借本文给大家分享,笔者对 Android 系统启动流程的整体理解~

hi, I’m Android
现在,按下电源键
下面是 Android 启动的核心步骤流程图,看文字的时候,记得回来对照图来理解喔,希望阅读全文后,回观流程图,会有恍然大悟的感觉,那么文章的目的就达到啦~
整体流程
一、启动电源及系统启动
系统从 ROM 中开始启动,加载引导程序到 RAM,然后执行。
二、引导程序
引导程序是 Android 操作系统开始运行前的一个小程序,因此它需要针对特定主板与芯片,并不是 Android 操作系统的一部分。引导程序是 OEM 厂商或运行商进行加锁、限制的地方。
1 两个阶段

检测外部 RAM 以及为第二阶段加载程序
设置网络、内存等,搭建内核运行环境(为了达到特殊目的时,引导程序可以根据配置参数或者输入数据来设置内核)

2 引导程序的加载器
Android 引导程序可以在 bootablebootloaderlegacyusbloader 找到,传统的加载器包含的两个文件:

init.s 初始化堆栈,清零 BSS 段,会调用 main.c 中的 _main() 函数(bss segment:通常是指用来存放程序中未初始化的全局变量的一块内存区域;BSS – Block Started by Symbol。BSS 段属于静态内存分配)
main.c 初始化硬件,创建 linux 标签

三、内核启动
Android 内核启动方式类似桌面 linux,主要步骤:
1. 设置缓存
2. 被保护存储器
3. 计划列表
4. 加载驱动
当内核完成系统设置,接下来即将启动系统的第一个进程 — init 进程
四、init 进程
作为 Android 系统的第一个进程,其 PID 为 0,通过解析 init.rc 脚本来构建出系统初始运行形态,这一阶段中,“Android”logo 会显示出来
(系统中,大多数系统服务程序都是在该脚本中描述并被相继启动的)
init.rc 由 4 种类型声明组成:Actions、Commands、Services、Options

Actions:响应某事件的过程。当“trigger”所描述的触发事件产生时,则依次执行各种“command”源码角度:系统会对 init.rc 中各“trigger”进行匹配,当发现符合条件的 Action,就将它加入“命令执行队列”尾部(除非 Action 已存在队列中),然后系统再对这些命令按顺序进行。on <trigger> ## 触发条件 <command1> ## 执行命令 <command2> ## 可执行多个命令 …

Commands:命令将在所属事件发生时被一个个执行

Services:可执行程序,它们在特定选项的约束下会被 init 程序运行或者重启(Service 可以在配置中指定是否需要退出重启,那么,当 Service 出现异常 crash 时,可有机会复原)service <name><pathname> [<argument>]* <option> <option>

Options: 对 service 的约束选项

五和六、ServiceManager、Zygote、SystemServer
科普:Daemons – 守护进程
init 进程通过解析 init.rc 来陆续启动其他关键的系统服务进程,其中最重要的是 ServiceManager、Zygote 和 SystemServer 三者,下面我们逐一解析:
1 ServiceManager — Binder 机制支撑者
概述:ServiceManager 是 Binder 机制中的支撑者,负责某 Binder 服务注册信息到底层 Binder 驱动分配的值解析。
ServiceManager 由 init 进程解析 rc 脚本时启动,属于 core 类,其他同类进程包括:uenetd、console、adbd 等。根据 core 组的特性,这些进程会同时启动或停止。另外,ServiceManager 配置含有 critical 属性,这意味着它是系统关键进程(如果进程不幸在 4 分钟内异常退出超过 4 次,设备将重启并进入还原模式)。当 ServiceManager 每次重启时,其他关键进程:zygote、media、surfaceflinger 等也会被 restart。
2. Zygote —“孕育”新线程与进程
Android 中大多数应用进程与系统进程都是通过 Zygote 来生成的。Zygote 同样由 init 解析 rc 脚本时启动,属于 main 类,同属 main 类的系统进程有:netd、debuggerd、rild 等。Zygote 并不是处于独立的程序中的,它所在程序名为“app_process”,观察 app_process 主函数实现知道,如果 init.rc 中指定了 –zygote 选项,app_process 接下来将启动“ZygoteInit”,并传入“start-system-server”, 这样,ZygoteInit 就会运行在虚拟机上(Dalvik VM)上了。

ZygoteInit 函数有两项重要工作
预装载各种系统类
搭建 SystemServer 环境,并启动 SystemServer(大部分的 Android 系统服务都在其中,由 Java 编写)

ZygoteInit 流程总结

摘自:Gityuan — Android 系统启动 -Zygote 篇

解析 init.zygote.rc 中的参数,创建 AppRuntime 并调用 AppRuntime.start() 方法;
调用 AndroidRuntime 的 startVM() 方法创建虚拟机,再调用 startReg() 注册 JNI 函数;
通过 JNI 方式调用 ZygoteInit.main(),第一次进入 Java 世界;
registerZygoteSocket() 建立 socket 通道,zygote 作为通信的服务端,用于响应客户端请求;
preload() 预加载通用类、drawable 和 color 资源、openGL 以及共享库以及 WebView,用于提高 ap 启动效率;
zygote 完毕大部分工作,接下来再通过 startSystemServer(),fork 得力帮手 system_server 进程,也是上层 framework 的运行载体。
zygote 功成身退,调用 runSelectLoop(),随时待命,当接收到请求创建新进程请求时立即唤醒并执行相应工作。

ZygoteInit 结束后,开机 Logo 就出来了。
(注意:这里并不包括开机动画,而是开机前“Android”Logo 出现的那个画面,开机动画出现之前还需要进行各种加载,开机动画是在“Android”Logo 出现之后才播放的)
3. SystemServer — 大部分 Android 系统服务所在地
SystemServer 是 Android 进入 Launcher 前的最后准备,它提供了众多的由“Java”语言编写的系统服务。
如果 init.rc 中为 zygote 指定启动参数 –start-system-server,那么 ZygotyeInit 就会调用 startSystemServer 来进入 SystemServer。

startSystemServer 函数解析:
首先 ZygoteInit 通过 Zygote.forkSystemServer 来生成一个新的线程(fork),用于承载各种系统服务。(源码角度:Zygote 内部由 Native 函数 Dalvik_dalvik_system_Zygote_forkSystemServer 来进一步实现,最终调用底层接口的 fork 接口来实际产生进程)
根据 fork 特性,子进程与父进程将获得相同的代码环境。pid 为 0 为子进程,否则为父进程;如果是前者,则进一步调用 handleSystemServerProcess(parseArgs) 函数来完成最核心的工作 —“启动各系统服务”(源码角度:handleSystemServerProcess 方法将 startSystemServer 中的 parsedArgs.remainingArgs 参数传给 RuntimeInit.zygoteInit,后者又调用 nativeZygoteInit 函数)
nativeZygoteInit 调用后,接着,三个重要的 static 函数就要被执行了:init1 – 完成本地 Service(SurfaceFlinger、AudioFlinger 等) 启动,完成后调用 init2、init2 – 新建一个新的带 Looper 的线程 ServerThread 来启动 Java 层各 Service

后语
上面对 Android 系统启动做了一个简述,意在给大家展现一个整体流程,其中每个环节涉及的知识点只是浅浅掠过,笔者也尚在学习与探索中,希望在后续再作详细分析。
资源推荐

Gityuan – Android 开篇
老罗的 Android 之旅
《深入理解 Android 内核设计思想》由浅入深,落实到源码层面上进行探索,知识很有深度

相关阅读【每日课程推荐】机器学习实战!快速入门在线广告业务及 CTR 相应知识

正文完
 0