Android系统启动过程学习
使用 android 手机已经长时间了,同时,从大学学习 android 开发开始,也进行过多款 android app 项目的开发,但是对 android 内部的启动过程,即当我们从按下电源键开机开始, android 系统内部是如何运行的,由于android系统的内核使用的是 linux 内核,那么在启动过程中,android 系统和桌面Linux系统的启动过程是否是一样的?我们在之前的一篇
使用 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”开机启动广播就发出去了。
更多推荐
所有评论(0)