Android 深入系统完全讲解

Posted 程序员入门进阶

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android 深入系统完全讲解相关的知识,希望对你有一定的参考价值。

1 系统启动过程、嵌入式系统启动过程

这是我之前画的启动过程的图,这个主要就是给大家讲明白,启动过程整个的流程。
第一个阶段,bootloader
系统在上电的时候,系统会从固定的地方加载一段代码进入内部 ram 进行运行。这段代码
通常是使用汇编语言编写,主要进行硬件的简单初始化,创建一个 c 语言所需要的堆栈区域,
然后加载 c 的代码运行。c 的代码完成更多的硬件设置,然后加载 kernel,进入操作系统初
始化。
第二阶段,操作系统初始化
当我们将 kernel 加载进入内存,从它的入口点进行继续初始化系统。第一阶段将硬件的状态
准备就绪,操作系统进行初始化所有配置的驱动代码,完成硬件驱动任务。然后在这个阶段,
将管理内存,网络,以及进程等等,完成了这些内容后,将启动第一个进程。
第三阶段,init 进程

当系统整个环境 OK 之后,就开始进入 init 进程,此进程进行挂载一些目录,解析 init.rc 配
置脚本,创建一些守护进程,在这些进程里面,主要的便是 Zygote,因为它是我们 android
上层架构的入口。
第四阶段,Zygote 进程
这个进程完成了 Android JAVA 虚拟机的构建,同时通过 JNI 配置,将本身 Zygote 的 c 系统进
行关联,将系统预置的资源,以及动态库进行加载,然后创建我们 Android 的系统服务进程。
系统服务进程,Zygote 完成了虚拟机的创建后,这时候就要进入 Android 的系统服务进程。
系统服务进程将我们应用开发的所需的服务启动起来,这里有 AMS,WMS,PMS 等一系列
服务。
启动完所有服务之后,这个时候就需要进入我们的桌面了,从此后我们就可以在桌面点击各
个应用入口,去看到各种各样的信息。
这里为什么要补充下嵌入式的启动过程,主要是要说下,嵌入式的启动过程简单,会让你避
免卷入在细节中,理解不了操作系统的启动。
这里分享一个 Window 启动过程,
电脑开机后,开始启动 Bios,开始 BIOS 自检。
通过自检后,bios 找到硬盘上的主引导记录 MBR. MBR 开始读取硬盘分区表 DPT,找到活动分区,找到活动分区中的分区引导记录 PBR,并且
把控制权交给 PBR. PBR 搜索活动区中的启动管理器 bootmgr,找到后,PBR 把控制权交给 bootmgr(相当于 xp
里的 ntldr 文件)。
Bootmgr 寻找活动分区中的 boot 文件夹中的 BCD 文件(启动配置数据,相当于 xp 里的 boo
t.ini 文件)。
找到 BCD 后,Bootmgr 首先从 BCD 中读取启动管理器 bootmgr 菜单的语言版本信息,然后
再调用 BOOTMGR 与相应语言的 BOOTMGR.EXE.MUI (在 boot 文件夹对应语言文件夹中)
组成相应语言的启动菜单,之后在显示器上显示多操作系统选择画面。7
如果存在多个操作系统而且系统设置的等待时间不是 0,那么屏幕就显示多个操作系统的选
择界面。如果没有多系统,那么直接进入 windows 7 系统,不显示选择界面。
选择 windows 7 系统后,bootmgr 就会读取 BCD 里 win7 系统所在的盘里的 windows\\system
32\\winload.exe 文件,并且将控制权交给 winload.exe。
Winload.exe 加载 windows7 内核、硬件、服务等,之后加载桌面等信息,从而启动整个 win
dows 7 系统。
上面几步可以概括一下就是:
BIOS–MBR–DPT–PBR–Bootmgr–BCD–系统选择界面—选择 windows7------Winload.exe----内核
加载等 --启动整个 windows7 系统 (这里只讲 win7)
如果学习嵌入式操作系统,推荐 ucos-ii 《ucos-ii 中文书》(邵贝贝),周立功也出了相关
的书籍。再一个后面接触的 ucLinux 和 freeRTOS,都可以在官网找到相关的学习资料。
操作系统是个硬实力,而且是程序员竞争中的一个核心能力,因为操作系统学会,基本上再
遇见各类设计,各种庞杂的结构,都能够很快的理解,吸收进来。这也是我一直强调的,也
是我自己很庆幸大学专门啃了这块知识。
我的学习路线在这里分享给你,C 语言开发,汇编,WIN32 汇编,数字电路,C51 单片机,
ARM 嵌入式,操作系统,UNIX 系统编程。
而操作系统是一直贯穿着,到工作后发现自学能力有了很强的突破,回头去看知道是死磕操
作系统的缘故。
2 init 初始化
我在这里把 init 进程的启动过程讲下,init 是 Linux 系统的第一个进程,进程号 1,Kernel 初
始化完成进程分配,内存管理等一系列动作后,就会启动第一个用户进程,推动系统进入桌
面。
我们从这个图可以看到,init 进程主要完成的动作,
挂载节点
构建 selinux 权限管理

开辟 prop 属性区域
解析 init.**.rc
死循环,等待属性变化,比如启动开机动画
那么按照我们之前讲的,怎么定位代码呢?当我们不知道代码在哪里的时候,可以在网页上
以关键字作为索引,还可以百度找下线索,而一般我们定位的时候,以锁定*.mk 和 *.bp 作
为检索文件约束,这个是安卓的编译配置,基本上系统中出来的都是在这种里面配置的。
我这里讲解的都会是技巧,如果说我们第一次不知道这些的话,就是全局检索,然后花费一
些时间去找,找到后记住一些目录,或者是文件后缀,后续类似的就可以进行推理。我们前
面讲的 am 命令的代码找寻技巧,大家也可以学习下。
我们依据 mk,定位到 system/core,找到了一个 LOCAL_MODULE:=init,打开看到里面配置
对应的是 include $(BUILD_EXECUTABLE),两个验证下就可以确定代码找对了。
我这里在分享个知识,定位到 BUILD_EXECUTABLE 具体是什么,这个目录很重要,基本上系
统编译相关的定义都在这里。(不要死记,而是用我的这个方法,我讲的都是策略,是通解,
这个才是能耐)

然后可执行文件,默认的入口是 main,是不是就可以从这个 mk 里面配置的目录中,定位一
个实现了 main 方法的文件,一般来讲我们的可执行名字,对应都有个对应的.c/.cpp,这里
就是 init.cpp
我们在研究这个 init 具体实现的时候,这里我们继续追一个代码,就是我们是不是说过 kernel
初始化完成后,就进入创建 init 进程。
那么我们找下这段代码,让整个的流程跑顺。这段实现是在 kernel,于是我们找到 kernel 目
录,进行检索。我们在这里看代码:
http://www.androidos.net.cn/androidkernel/4.1
这里因为 init 很多,都是 c,于是就直接按照最终定位到的给大家讲,这块要学习的话,需
要去读 kernel 的代码,而我前面推荐的嵌入式的就是最好的学习方法。

然后我们要定位参数,可以使用这个,这里我使用的是虚拟机,而且是 x86 系统,一般情况
下我们是 arm 的板子,但是这块不影响结果,于是我们看到这里调用的是/init 这个进程。

那么我们这里就是看下 init 的入口,要详细分析的参考对应文档即可,我们这里主要就是说
下 init 的进程创建过程,让大家能够清楚的知道来源,后续想跟踪可以轻松定位。
那么回过头来,我们来说下 init 的代码,这是我们今天的主菜。它的代码路径是在
system\\core\\init ,这个 system\\core 路径也是需要多看,一些守候进程,一些底层库都在这个
路径下放着。

这里我们找的时候,直接検索 main 方法,这个就是最直接的方法找入口。C 语言程序会有
入口 main,如果是嵌入式的话,很有可能会定义成别的,比如 #define WINMain main 就
这种。
main.cpp 直接调用 init 的 main 方法,于是我们从 init 直接去看。(我这边用的 Android 9.0
的代码)
init 多用的,依据参数不同可以触发不同的代码,我们不分析无关的,直接到最下面看 init
的代码。Init 是分为两阶段的,通过第一阶段操作完后,清空堆栈,进入第二阶段。
第一阶段完成一些节点的挂载,设置权限。然后调用 SelinuxInitilize 设置 SELinux 相关的初始
化。

利用系统方法 execv 直接替换,进入第二阶段,也就是从这里就直接又走到了 main 方法,
进入第二阶段了。具体的原理需要参考 Linux 内核的 exec 方法的讲解去了解内部实现。
属性初始化在这里,后面研究属性会讲到。
启动服务,开始解析我们的脚本。处理完之后便进入循环,等待系统给的属性改变信号。
而具体的细节,可以去看代码了解,因为这个不是本书的目的,我主要要讲清楚流程,分析
过程,细节定位需要慢慢看,我们在学习代码的时候,就是几个招,这里分享给大家:

打印 Log,打印堆栈,调试,以及阅读源码
什么别人给的流程图,其实只是给你一个线索而已,剩下的就是交给自己去跟踪的,这个才
是正确的学习方法。那么在解析 rc 的时候,有个/init.$ro.zygote.rc ,这个是对应的 zygote
的配置,我们这里是:
那么我们知道了 service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote
–start-system-serve
那么我们进入 zygote 的创建过程。这里顺便说下,跟着我的课程学习,会发现很有趣的一
点是框架性的东西很多,细节的东西会忽略,因为这些细节都是干扰项,对于学习来讲只会
让你困惑。
我们要的是先掌握框架,然后再细跟某个细节,如果一本书讲那么多细节,其实你学的时候
也没法理解。毕竟写书的人,也是不断调试,补充内容的,我们要的就是不断调试,而不是
死记他们的结果。
这里说下我们的很多守护进程都是 init 创建的,我们可以使用 ps -A 去看每个进程的父进程,
如果是 init 就是它创建的,这里想说下有一些服务需要说下。
servicemanager 和 surfaceflinger 一个是管理系统所有 Binder 服务的,一个是绘制底层实现,
上层通过创建 Window,最终跟 surfaceflinger 的 Layer 进行关联,实现窗口位置,绘制的逻
辑。
关于 servicemanager 我们会讲,surfaceflinger 只是大致提一下,要不然这个书就兜不住了,
太长,因为这块很多人也分析过,如果专门做绘制相关的需要了解下。
以上是我的学习技巧,这里不做讨论。我们进入 zygote 的学习,go go go!

以上是关于Android 深入系统完全讲解的主要内容,如果未能解决你的问题,请参考以下文章

Android 深入系统完全讲解(31)

Android 深入系统完全讲解(31)

Android深入系统完全讲解(38)

Android深入系统完全讲解(38)

Android 深入系统完全讲解(25)

Android 深入系统完全讲解(25)