使用 android 手机已经长时间了,同时,从大学学习 android 开发开始,也进行过多款 android app 项目的开发,但是对 android 内部的启动过程,即当我们从按下电源键开机开始, android 系统内部是如何运行的,由于android 系统的内核使用的是 linux 内核,那么在启动过程中,android 系统和桌面Linux系统的启动过程是否是一样的?我们在之前的一篇博客中,曾学习过Linux内核的启动过程,在这里,我们学习一下android系统的启动过程,并从大体代码上讲解其启动过程。
启动步骤
在android系统的启动过程中,大体可以分为以下几个步骤:
android启动过程分析
第一步 启动电源以及启动系统
当电源按下的时候,会引导固化在芯片中的代码从预定义的位置开始启动,并加载引导程序到内存,即RAM中,然后执行。
第二步 引导程序运行
引导程序,英文名称为Boot Loader,顾名思义,其为启动加载器,其主要作用是引导android系统内核的启动。引导程序是运行的第一个程序。其主要作用是在引导内核启动之前,检测相关硬件以及外部的RAM,设置网络,内存等,并根据相关参数或输入数据设置内核。
Boot Loader引导程序可以在\bootable\bootloader\legacy\usbloader
中找到,一般的加载器包含着两个重要的文件:
- init.S初始化堆栈,清空BBS栈,调用main.c的_main()函数
- main.c初始化硬件(闹钟,主板,键盘,控制台),创建Linux标签
第三步 内核运行
当引导程序引导内核启动之后,android的内核运行和linux的内核运行相似。内核启动的时候,设置缓存,被保护的存储器,计划列表,加载驱动。当内核完成系统设置之后,便找到系统文件中”init”文件,然后启动系统的第一个进程。
第四步 init运行
init进程是android系统运行的第一个进程,也就是说所有的android进程都是直接或间接的被init进程创建的。在init进程运行过程中,主要负责两个事情,一个是挂载系统目录,像/dev
,/proc
,/sys
等,另外一件事情是执行init.rc
文件。
init
位于/system/core/init
目录中。init.rc
位于/system/core/rootdir
目录中。- 在
/system/core/init/readme.txt
文件中可以学习.rc
文件的相关语法,我们将在下面的博客中学习该语法。
总体来说,在init.rc
文件中,主要是启动相关进程和服务,同时设置相关参数和挂载相关目录。
我们先来看一下init
中的相关代码:
int main(int argc, char **argv)
{
//.....
#ifndef NO_DEVFS_SETUP
mkdir("/dev", 0755);
mkdir("/proc", 0755);
mkdir("/sys", 0755);
mount("tmpfs", "/dev", "tmpfs", MS_NOSUID, "mode=0755");
mkdir("/dev/pts", 0755);
mkdir("/dev/socket", 0755);
mount("devpts", "/dev/pts", "devpts", 0, NULL);
mount("proc", "/proc", "proc", 0, NULL);
mount("sysfs", "/sys", "sysfs", 0, NULL);
close(open("/dev/.booting", O_WRONLY | O_CREAT, 0000));
open_devnull_stdio();
klog_init();
#endif
property_init();
//.......
is_charger = !strcmp(bootmode, "charger");
INFO("property init\n");
if (!is_charger)
property_load_boot_defaults();
INFO("reading config file\n");
if (!charging_mode_booting())
init_parse_config_file("/init.rc");
else
init_parse_config_file("/lpm.rc");
/* Check for an emmc initialisation file and read if present */
if (emmc_boot && access("/init.emmc.rc", R_OK) == 0) {
INFO("Reading emmc config file");
init_parse_config_file("/init.emmc.rc");
}
/* Check for a target specific initialisation file and read if present */
if (access("/init.target.rc", R_OK) == 0) {
INFO("Reading target specific config file");
init_parse_config_file("/init.target.rc");
}
//.......
在这些事情处理完成之后,在init.rc
中便会启动zygote进程。
service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
class main
socket zygote stream 660 root system
onrestart write /sys/android_power/request_state wake
onrestart write /sys/power/state on
onrestart restart media
onrestart restart netd
第五步 zygote进程
在java中不同的虚拟机实例会为不同的应用分配不同的内存。假如android应用应该尽可能快的启动,但如果android系统为每一个应用启动不同的Dalvik虚拟机实例,就会消耗大量的内存以及时间。因此为了解决这个问题,Android系统创造了Zygote。Zygote让Dalvik虚拟机共享代码,低内存占用以及最小的启动时间成为可能。Zygote是一个虚拟机进程,正如我们在前一个步骤所说的在系统引导的时候启动。Zygote预加载以及初始化核心库类。
Zygote加载进程:
public static void main(String argv[]) {
try {
// Start profiling the zygote initialization.
SamplingProfilerIntegration.start();
registerZygoteSocket();
EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,
SystemClock.uptimeMillis());
preload();
EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,
SystemClock.uptimeMillis());
// Finish profiling the zygote initialization.
SamplingProfilerIntegration.writeZygoteSnapshot();
// Do an initial gc to clean up after startup
gcAndFinalize();
// Disable tracing so that forked processes do not inherit stale tracing tags from
// Zygote.
Trace.setTracingEnabled(false);
// If requested, start system server directly from Zygote
if (argv.length != 2) {
throw new RuntimeException(argv[0] + USAGE_STRING);
}
if (argv[1].equals("start-system-server")) {
startSystemServer(); //启动系统服务
} else if (!argv[1].equals("")) {
throw new RuntimeException(argv[0] + USAGE_STRING);
}
Log.i(TAG, "Accepting command socket connections");
runSelectLoop();
closeServerSocket();
} catch (MethodAndArgsCaller caller) {
caller.run();
} catch (RuntimeException ex) {
Log.e(TAG, "Zygote died with exception", ex);
closeServerSocket();
throw ex;
}
}
- 加载
ZygoteInit
类,代码位于/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
中。 registerZygoteSocket()
为zygote命令连接注册一个服务器套接字。preload()
预加载类,资源文件以及OpenGL。
第六步 系统服务或服务
在Zygote完成相应的初始化之后,开始申请启动系统服务,系统服务是android系统中供上层运行的基础。系统服务同时使用native以及java编写,系统服务可以认为是一个进程。同一个系统服务在Android SDK可以让System Services形式获得。
核心服务:
- 启动电源管理器;
- 创建Activity管理器;
- 启动电话注册;
- 启动包管理器;
- 设置Activity管理服务为系统进程;
- 启动上下文管理器;
- 启动系统Context Providers;
- 启动电池服务;
- 启动定时管理器;
- 启动传感服务;
- 启动窗口管理器;
- 启动蓝牙服务;
- 启动挂载服务。
其他服务:
- 启动状态栏服务;
- 启动硬件服务;
- 启动网络状态服务;
- 启动网络连接服务;
- 启动通知管理器;
- 启动设备存储监视服务;
- 启动定位管理器;
- 启动搜索服务;
- 启动剪切板服务;
- 启动登记服务;
- 启动壁纸服务;
- 启动音频服务;
- 启动耳机监听;
- 启动AdbSettingsObserver(处理adb命令)。
第七步 引导完成
一单系统服务启动,android系统的引导过程就完成了。此时,”ACTION_BOOT_COMPLETE”开机启动广播就发出去了。