源码级分析Android系统启动流程
首先看一下Android系统的体系结构,相信大家都不陌生

1.首先Bootloader引导程序启动完Linux内核后,会加载各种驱动和数据结构,当有了驱动以后,开始启动Android系统,同时会加载用户级别的第一个进程init(system\core\init.c),该进程会首先加载一个init.rc配置文件,代码如下
int main(int argc, char **argv)
{
// 创建文件夹 挂载
mount("tmpfs", "/dev", "tmpfs", 0, "mode=0755");
mkdir("/dev/pts", 0755);
// 打开日志
log_init();
INFO("reading config file\n");
// 加载init.rc配置文件
init_parse_config_file("/init.rc");
}
2.init.rc配置文件会进行很多的配置,创建很多的文件夹及文件,然后初始化一些Android驱动器,之后该配置文件最重要的一个任务就是启动一个Zygote(孵化器)进程,此进程是Android系统的一个母进程,用来启动Android的其他服务进程,代码:
service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
socket zygote stream 666
onrestart write /sys/android_power/request_state wake
onrestart write /sys/power/state on
onrestart restart media
onrestart restart netd
3. Zygote会执行一个app_process可执行文件,在这个文件中首先添加了Android运行时环境,在Android运行时中调用了ZygoteInit.java,这就从c++代码跳到了java代码。
int main(int argc, const char* const argv[])
{
...
// Android运行时环境
AppRuntime runtime;
...
// Next arg is startup classname or "--zygote"
if (i < argc) {
arg = argv[i++];
if (0 == strcmp("--zygote", arg)) {
bool startSystemServer = (i < argc) ?
strcmp(argv[i], "--start-system-server") == 0 : false;
setArgv0(argv0, "zygote");
set_process_name("zygote");
// 启动java代码
runtime.start("com.android.internal.os.ZygoteInit",
...
}
4.在ZytofeInit.java代码中首先设置了Java虚拟机的堆内存空间,然后启动一个类加载器加载Android启动依赖的类比如Activity等四大组件,dialog等UI的类,然后分出一个子进程启动SystemServer系统服务
public static void main(String argv[]) {
try {
VMRuntime.getRuntime().setMinimumHeapSize(5 * 1024 * 1024);
// 加载Android依赖的类
preloadClasses();
//cacheRegisterMaps();
preloadResources();
...
if (argv[1].equals("true")) {
// 启动系统服务
startSystemServer();
} else if (!argv[1].equals("false")) {
...
}
private static boolean startSystemServer()
...
args = new String[] {
"--setuid=1000",
"--setgid=1000",
"--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,3001,3002,3003,3006",
"--capabilities=130104352,130104352",
"--rlimit=8,",
"--runtime-init",
"--nice-name=system_server",
"com.android.server.SystemServer",
...
/* Request to fork the system server process */
// 母进程开始分叉服务 启动SystemServer
pid = Zygote.forkSystemServer(
parsedArgs.uid, parsedArgs.gid,
parsedArgs.gids, debugFlags, rlimits,
parsedArgs.permittedCapabilities,
parsedArgs.effectiveCapabilities);
...
}
5.在SystemServer.java代码中有两个方法init1()启动Native世界,init2()启动Android的Framework世界
public static void main(String[] args) {
...
// 加载jni库
System.loadLibrary("android_servers");
// 调用native方法,该方法启动Native世界
init1(args);
}
native public static void init1(String[] args);
6.SystemServer首先调用init1()方法加载JNI库,启动Native世界。init1通过System.loadLibrary("android-servers")加载一个类库文件,其对应的源码文件为com_android_server_SystemServer.cpp 其C++代码如下,在该类库中转调了system_init()方法
// 类似java的抽象方法
extern "C" int system_init();
static void android_server_SystemServer_init1(JNIEnv* env, jobject clazz)
{
// 转调
system_init();
}
/*
* JNI registration.
*/
static JNINativeMethod gMethods[] = {
/* name, signature, funcPtr */
// 函数指针 把init1方法映射到android_server_SystemServer_init1
{ "init1", "([Ljava/lang/String;)V", (void*) android_server_SystemServer_init1 },
};
7.System_init方法在System_init.cpp中实现,它首先启动系统的硬件服务,比如Audio、Camera等,启动完硬件服务后它又通过Android运行时环境调用了SystemServer中的init2()方法,init2()方法启动Framework世界,代码如下:
extern "C" status_t system_init()
{
...
// 启动硬件的服务
if (strcmp(propBuf, "1") == 0) {
// Start the SurfaceFlinger
SurfaceFlinger::instantiate();
}
AndroidRuntime* runtime = AndroidRuntime::getRuntime();
LOGI("System server: starting Android services.\n");
// 启动完硬件服务后,又回到Systemserver的init2方法
runtime->callStatic("com/android/server/SystemServer", "init2");
...
}
8.SystemServer的init2方法,init2()方法启动Android的Framework层,启动Android世界。在该方法中启动了一个ServerThread线程,其代码如下:
public static final void init2() {
Slog.i(TAG, "Entered the Android system server!");
Thread thr = new ServerThread();
thr.setName("android.server.ServerThread");
thr.start();
}
9.init2()启动的线程ServerThread中的的run方法中通过一个Looper开启了Android中的各种服务比如LightService,PowerManagerService,BatteryService,WindowManagerService等,并将服务添加到ServiceManager中去管理,启动完各种服务后,调用ActivityManagerService.systemReady方法:
public void run() {
...
// 开启Android各种服务并且添加到ServiceManager去管理
Slog.i(TAG, "Device Policy");
devicePolicy = new DevicePolicyManagerService(context);
ServiceManager.addService(Context.DEVICE_POLICY_SERVICE, ottle =
...
// We now tell the activity manager it is okay to run third party
// code. It will call back into us once it has gotten to the state
// where third party code can really run (but before it has actually
// started launching the initial applications), for us to complete our
// initialization.
// 各种服务开启后调用ActivityManagerService.systemReady
((ActivityManagerService)ActivityManagerNative.getDefault())
.systemReady(new Runnable() {
public void run() {
Slog.i(TAG, "Making services ready");
10.在ActivityManagerService的systemReady方法中打开Android系统的第一个Activity
public void systemReady(final Runnable goingCallback) {
...
// 打开第一个Activity
mMainStack.resumeTopActivityLocked(null);
}
}
11.ActivityStack的resumeTopActivityLocked方法启动home界面
final boolean resumeTopActivityLocked(ActivityRecord prev) {
// Find the first activity that is not finishing.
// 没有已经打开的Activity, next为 null
ActivityRecord next = topRunningActivityLocked(null);
// Remember how we'll process this pause/resume situation, and ensure
// that the state is reset however we wind up proceeding.
final boolean userLeaving = mUserLeaving;
mUserLeaving = false;
if (next == null) {
// There are no more activities! Let's just start up the
// Launcher...
if (mMainStack) {
// 启动lucher应用的锁屏界面
return mService.startHomeActivityLocked();
}
}
12.打开了Luncher应用的Home界面之后,到此Android系统启动完成了。
可以把整个过程总结为如下这张图

源码级分析Android系统启动流程的更多相关文章
- MapReduce的ReduceTask任务的运行源码级分析
MapReduce的MapTask任务的运行源码级分析 这篇文章好不容易恢复了...谢天谢地...这篇文章讲了MapTask的执行流程.咱们这一节讲解ReduceTask的执行流程.ReduceTas ...
- RxJava && Agera 从源码简要分析基本调用流程(2)
版权声明:本文由晋中望原创文章,转载请注明出处: 文章原文链接:https://www.qcloud.com/community/article/124 来源:腾云阁 https://www.qclo ...
- MapReduce的MapTask任务的运行源码级分析
TaskTracker任务初始化及启动task源码级分析 这篇文章中分析了任务的启动,每个task都会使用一个进程占用一个JVM来执行,org.apache.hadoop.mapred.Child方法 ...
- TaskTracker任务初始化及启动task源码级分析
在监听器初始化Job.JobTracker相应TaskTracker心跳.调度器分配task源码级分析中我们分析的Tasktracker发送心跳的机制,这一节我们分析TaskTracker接受JobT ...
- 监听器初始化Job、JobTracker相应TaskTracker心跳、调度器分配task源码级分析
JobTracker和TaskTracker分别启动之后(JobTracker启动流程源码级分析,TaskTracker启动过程源码级分析),taskTracker会通过心跳与JobTracker通信 ...
- TableInputFormat分片及分片数据读取源码级分析
我们在MapReduce中TextInputFormat分片和读取分片数据源码级分析 这篇中以TextInputFormat为例讲解了InputFormat的分片过程以及RecordReader读取分 ...
- MapReduce job在JobTracker初始化源码级分析
mapreduce job提交流程源码级分析(三)中已经说明用户最终调用JobTracker.submitJob方法来向JobTracker提交作业.而这个方法的核心提交方法是JobTracker.a ...
- Shell主要逻辑源码级分析(1)——SHELL运行流程
版权声明:本文由李航原创文章,转载请注明出处: 文章原文链接:https://www.qcloud.com/community/article/109 来源:腾云阁 https://www.qclou ...
- 【原创】源码角度分析Android的消息机制系列(三)——ThreadLocal的工作原理
ι 版权声明:本文为博主原创文章,未经博主允许不得转载. 先看Android源码(API24)中对ThreadLocal的定义: public class ThreadLocal<T> 即 ...
随机推荐
- Java 分割文件 注意事项
public static void main(String args[]) throws Exception { if (args.length < 1) { System.exit(0); ...
- win7中protel99添加元件库
protel打开时默认添加Miscellaneous Devices.lib,点击ADD/REMOVE按钮添加所需要的库时,弹出“文件无法识别”. 点击面板右下方“FIND”按钮,弹出如下对话框时不要 ...
- python install 2.7.10
CentOS 6.5升级Python和安装IPython 后来换成了CentOS 6.5,系统自带的Python版本是2.6.6. 图一:安装IPython需求 已经安装好gcc等编译工具.系统自带P ...
- mediawiki 的使用 2
要想外部电脑能访问你的网站,网站部署好后,在LocalSettings.php 里将这句 $wgServer = "http://localhost"; 改成 $wgServer ...
- Python和Django的Third Libraby分类汇总
这些第三方包与Python和Django一起构成了强大的生态系统,自己在开发时大大减小工作难度和工作量, 这些包基本上能满足我们的大部分需求.人与人的差距,其中一点是你知道的比他多,这样你就能大大提高 ...
- rapsbian下配置ngrok
访问https://ngrok.com,下载Linux/ARM版本的(因为PI为ARM的芯片,如果下载Linux版本的是无法正常使用的) 解压 $ unzip /path/to/ngrok.zip 注 ...
- STL学习系列七:优先级队列priority_queue容器
1.简介 最大值优先级队列.最小值优先级队列 优先级队列适配器 STL priority_queue 用来开发一些特殊的应用,请对stl的类库,多做扩展性学习 这里给个例子: #include< ...
- 几种连接不同数据库的ADO.NET字符串
Data Source=myServerAddress;Initial Catalog=myDataBase;User Id=myUsername;Password=myPassword;或者 Ser ...
- <MFC_1>深入剖析MFC的WinMain和消息机制
一.开篇引论 熟悉Win32开发的朋友,应该非常了解它的基本组成和流程 1. WinMain:书写窗口类(WNDCLASS) -> 注册窗口类 -> 创建窗口 -> 显示窗口和更新窗 ...
- Codeforces 660 C. Hard Process (尺取)
题目链接:http://codeforces.com/problemset/problem/660/C 尺取法 #include <bits/stdc++.h> using namespa ...