Android的启动从长按电源键开始,先加载ROM中的引导程序Bootloader、Linux内核到RAM中;然后执行第一个用户级进程Init,Init进程分析和运行init.rc文件,运行Zygote和ServiceManager等服务;Zygote创建一个Socket,循环等待和处理应用程序的启动请求,同时Zygote还会启动SystemServer;SystemServer会启动各个服务,比如AMS,WMS,PMS;最后AMS启动Launcher。

一、Init

Init进程为Linux内核启动的第一个用户级进程,它主要负责生成并挂载设备驱动节点,分析及运行init.rc文件,执行init.rc中的early-init、init、early-boot、boot列表,包括设置环境变量、生成并挂载系统运行时需要的文件和目录、应用程序的驱动文件和目录、并修改相应权限,并开启一些服务,如Zygote和ServiceManager等服务。

init.rc位于system/core/rootdir/目录下,可自行查看https://www.androidos.net.cn/android/10.0.0_r6/xref/system/core/rootdir/init.rc

二、Zygote

1. init.zygotexx.rc

init.zygotexx.rc位于system/core/rootdir/目录下,内容如下:

service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server
class main
priority -20
user root
group root readproc reserved_disk
socket zygote stream 660 root system
socket usap_pool_primary stream 660 root system
onrestart write /sys/android_power/request_state wake
onrestart write /sys/power/state on
onrestart restart audioserver
onrestart restart cameraserver
onrestart restart media
onrestart restart netd
onrestart restart wificond
writepid /dev/cpuset/foreground/tasks

对上述内容简单介绍下,以服务形式启动 Zygote,其目录为 /system/bin/app_process64,后接了一些参数,其中启动了 Zygote后会启动SystemServer。 Zygote定义了一个名为"zygote"的Socket,这个Socket将用于监听应用程序的启动请求。该服务重新启动会重启audioserver、cameraserver等。

2. ZygoteInit

Zygote的入口为:https://www.androidos.net.cn/android/10.0.0_r6/xref/frameworks/base/cmds/app_process/app_main.cpp, 在main函数中创建了一个AppRuntime对象,再通过AppRuntime的start函数创建一个虚拟机实例,开启ZygoteInit.java,并传入参数start-system-server。

ZygoteInit的入口为main函数,它创建一个Socket对象,用于监控系统进程和应用程序进程的启动请求。再判断传入的参数是否包含start-system-server,是则启动系统进程。最后通过runSelectLoopMode函数循环等待和处理启动请求。

3. fork

Zygote启动进程是通过调用Zygote的forkAndSpecialize函数,该函数是调用了fork函数创建进程,fork函数是典型的调用一次,返回两次的函数,调用进程(父进程)返回子进程的PID,而子进程返回0。

所以在下图中,可以看到com.ss.android.article.news的父进程为zygote。

root 1089 1 1764064 111176 do_sys_poll 0 S zygote

u0_a174 7885 1089 2484968 211924 do_epoll_wait 0 S com.ss.android.article.news

系统进程和应用程序进程通过复制Zygote获得一个虚拟机实例拷贝。在创建新的进程时,拷贝Zygote的虚拟存储空间到子进程,虚拟存储空间分用户空间和内核空间,因为内核空间是一一映射了物理内存,所以所有的进程都共享了内核线性地址空间。

fork函数调用完成以后父进程的虚拟存储空间被拷贝给了子进程的虚拟存储空间,实现了共享文件等操作。但是虚拟的存储空间映射到物理的存储空间的过程采用了写时拷贝技术,即多个进程中同样的数据在物理的存储空间只有一个,而当其中的某一个进程试图对该区域进行写操作时,内核就会在物理的存储空间中开辟一个新的物理存储空间,将需要写的区域复制到新的物理页面中,然后对新的物理页面进行写操作。

三、SystemServer

Zygote通过调用forkSystemServer函数fork出子进程(SystemServer进程),关掉复制来的Zygote的Socket,再调用handleSystemServerProcess函数,启动SystemServer.java。

SystemServer的入口为main函数, 它会去启动一系列系统服务,并将服务注册到ServiceManager中,包括常用的AMS,WMS,PMS等服务。SystemServer又会调用AMS的systemReady函数,该函数中会去启动Launcher。

最后,贴一张Gityuan博客中的Android系统的启动流程图:

Android系统的启动流程图