前言
在一个夜黑风高的晚上,我的男同事突然给我发了一条微信,我点开来看,他竟然问我Android从按下开机键到启动到底发生了什么?此刻我的内心如下图:但是作为一个Android开发者,了解整个系统架构是必须的,所以这篇就总结一下Android手机从按下开机键到启动这一过程发生了什么。
要了解Android手机启动过程,我们先来了解一下基于linux系统的电脑从按下电源键的那一刻起,发生了什么,这样类比可以更好的理解Android手机的启动过程。
基于Linux的pc启动过程
我们都知道,所有的程式软件包括操作系统都是执行在内存中的,然而我们的操作系统一般是存放在硬盘上的,当我们按下开机键的时候,此时内存中什么程式也没有,因此需要借助某种方式,将操作系统载入到内存中,而完成这项任务的就是 BIOS 。装过系统的人一定知道BIOS这个东西,那么它究竟是什么呢?
BIOS:Basic Input/Output System(基本输入输出系统),在IBM PC相容系统上,是一种业界标准的固件界面(来自维基百科)。有点难以理解,其实BIOS是我们电脑启动时载入的第一个程式,这个程式不是由Java语言编写也不是由C语言编写,一般是汇编程式。
BIOS程式固化在主板上的一块芯片上,是连线计算机硬件与操作系统的桥梁,它储存着计算机最重要的基本输入输出的程式、开机后自检程式和系统自启动程式。
那么问题来了,BIOS程式又是怎么启动的?BIOS的启动,是由硬件完成的,Intel 80x86系列的cpu的硬件都设计为加电(即开机瞬间)就进入16位真实模式状态执行,此时将cpu的硬件逻辑设计为强行将CS的值设定为0xFFFF,IP的值设定为0x0000,这样CS:IP就指向了0xFFFF0这个位置,而这个位置就是BIOS程式的入口地址。
因此这是一个硬件厂商之间的约定,所有的BIOS程式入口地址均为0xFFFF0,这样在开机的时候,就找到这个地址,如果该地址并没有程式码段,那么计算机将会宕机,如果这个地址处有程式码段,将会执行这个程式码段,并由此执行下去,即BIOS程式开始启动。
补充:
CS:程式码段暂存器,存在于CPU中,指向CPU当前执行程式码在内存中所在的区域。
IP:指令暂存器,存在于CPU中,记录将要执行的指令在程式码段内的偏移地址,与CS组合即为将要执行的指令的内存地址。
当BIOS程式启动时,就会检测硬件装置,比如我们的显卡、内存等资讯。BIOS会在内存中建立中断向量表和中断服务程式。中断向量表中有256个中断向量,每个中断向量占4个字节,每个中断向量指向一个中断服务程式,这些中断服务程式完成了将操作系统由硬盘载入到内存中的任务.
基于linux的操作系统而言,计算机将分三批逐次载入操作系统的程式码,第一批由BIOS中断int 0x19将 第一扇区bootsect的内容载入到内存;第二批和第三批在bootsect的指挥下,分别载入后面扇区的内容到内存中。
经过执行一系列的BIOS程式码后,计算机完成了自检等操作,计算机硬件体系会与BIOS联合操作,让cpu接收到一个int 0x19中断,cpu接收到这个中断后,会立即在中断向量表中找到int 0x19中断向量,此时会找到对应的中断服务程式,并由该中断服务程式将硬盘中第一个扇区的载入程式加在到内存中的指定位置。
随后,在载入程式的作用下,陆续将操作系统的其他程式载入内存,完成真实模式到保护模式的转变,为执行操作系统的入口函式main做准备,后面就是操作系统的初始化工作了,最后完成计算机的启动。
Android手机的启动过程
Android系统虽然也是基于linux系统的,但是由于Android属于嵌入式装置,并没有像pc那样的BIOS程式。取而代之的是Bootloader ——系统启动载入器。它类似于BIOS,在系统载入前,用以初始化硬件装置,建立内存空间的映像图,为最终呼叫系统核心准备好环境。
在Android里没有硬盘,而是ROM ,它类似于硬盘存放操作系统,使用者程式等。ROM跟硬盘一样也会划分为不同的区域,用于放置不同的程式,在Android中主要划分为一下几个分割槽:
/boot:存放载入程式,包括核心和内存操作程式/system:相当于电脑c盘,存放Android系统及系统应用/recovery:恢复分割槽,可以进入该分割槽进行系统恢复/data:使用者资料区,包含了使用者的资料:联络人、简讯、设定、使用者安装的程式/cache:安卓系统快取区,储存系统最常访问的资料和应用程序/misc:包含一些杂项内容,如系统设定和系统功能启用禁用设定/sdcard:使用者自己的储存区,可以存放照片,音乐,视讯等档案那么Bootloader是如何被载入的呢?我们可以想到,应该跟pc一样,当开机加电的时候,cpu会从cpu制造厂商预设的地址上取指令,这个地址是各厂商约定俗称的,类似于上面80x86架构里的0xFFFF0地址,因此Android手机会将固态储存装置ROM预先对映到该地址上,当开机加电的时候,cpu就会从该地址执行/boot分割槽下的Bootloader程式,载入linux核心到RAM中。
当linux核心启动后会初始化各种软硬件环境,载入驱动程式,挂载根档案系统,并开始执行根档案系统的init程式,init程式是Android启动过程中最重要的核心程式。
init程序是Android系统中使用者程序的鼻祖程序。init程序会启动各种系统本地服务,如:Media Server、Service Manager、bootanim(开机动画)等。init程序会在解析init.rc档案后fork出Zygote,而Zygote是所有Java程序的父程序,我们的App都是由Zygote fork出来的。
Zygote程序主要包含:
载入ZygoteInit类,注册Zygote Socket服务端套接字;载入虚拟机器;预载入Android核心类预载入系统资源随后Zygote程序会fork出System Server程序,System Server程序负责启动和管理整个framework,包括Activity Manager,PowerManager等服务。
当System Server将系统服务启动就绪后,就会通知ActivityManager启动首个Android程式Home即我们看到的桌面程式。
至此,从Android手机开机到看到桌面程式所有过程分析完了。
最后附一张整体流程图,帮助更好理解:
本人14年java转Android开发,去阿里,华为等大厂待过,也面试过很多人。不少人私下问我,2019年Android进阶该怎么学,方法有没有?深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长,不成体系的学习效果低效漫长且无助。
没错,三月份开始我花了一个多月的时间整理出来的学习资料,希望能帮助那些想进阶提升Android开发,却又不知道怎么进阶学习的朋友。【包括高阶UI、效能优化、架构师课程、NDK、Kotlin、混合式开发(ReactNative+Weex)、Flutter等架构技术资料】,希望能帮助到您面试前的复习且找到一个好的工作,也节省大家在网上搜索资料的时间来学习。
资料获取方式:转发+关注后私信回复我【学习】免费获取Android进阶开发资料!!!