作为 Android 开发者,你真的知道 Android 按下开机键到启动发生什么吗?
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 手机开机到看到桌面程序所有过程分析完了。
最后附一张整体流程图,帮助更好理解:
最后
如果你看到了这里,觉得文章写得不错就给个赞呗?如果你觉得那里值得改进的,请给我留言。一定会认真查询,修正不足。谢谢。
评论