本文主要是介绍Android 系统启动流程源码分析,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
一、Init进程启动
是一个由内核启动的用户级进程。内核自行启动之后,就通过启动一个用户级程序init的方式,完成引导进程。
启动的代码init.c中的main函数执行过程:system\core\init.c中:
主要下面两个重要的过程:
1、rc文件解析
进入解析函数,把解析出来的东西放入相应的类型(List)
2、执行command和processes
进入死循环:执行execute_one_command和restart_processes
第二个原函数调用关系如下
准备启动service:service_start_if_needed
启动service的主要入口函数:service_start
创建进程函数:fork
执行新的service:execve
下面启动zygote为例子,在init.rc有这样一段描述
而svc->args[0]的值就是上面反选的代码。
函数execve(执行文件)说明: execve()用来执行参数filename字符串所代表的文件路径,第二个参数系利用数组指针来传递给执行文件,最后一个参数则为传递给执行文件的新环境变量数组。
返回值 如果执行成功则函数不会返回,执行失败则直接返回-1。
上面是sercice启动,下面在再举个action启动流程的例子
在这里触发,加入到action队列:
在init.c中main函数有这样一段代码:表示执行action队列
init.rc有这样一段描述
单执行到early-init的时候,就会启动这个函数.rc的start对应do_start,看下面代码片段:
进入do_start函数:
把参数early-init传入service_start函数,启动init进程,由于kernel启动的时候就已经启动了init进程,所以直接进入init进程的main函数了,看下面描述就会明白:
因为ueventd 和 Init 在同一个可执行文件下,因此在启动ueventd进程时,进程入口函数依然是main,进入main函数:
然后进入ueventd_main函数,完成!
二、启动serviceManager
在脚本文件Init.rc的描述,其中/system/bin/servicemanager adb shell 在小机端可以看到:
看看下面就知道对应源码的位置了:
打开Android.mk内容如下:
看到了: LOCAL_MODULE := servicemanager,而servicemanager就是上述.rc的servicemanager对应,所以源码就是service_manager.c;最后,使用include $(BUILD_EXECUTABLE)表示以一个可执行程序的方式进行编译。
源码的位置为:frameworks\base\cmds\servicemanager\service_manager.c
servicemanager用来管理系统中所有的binder service,不管是本地的c++实现的还是java语言实现的都需要这个进程来统一管理,最主要的管理就是,注册添加服务,获取服务。所有的Service使用前都必须先在servicemanager中进行注册。主要函数如下:
do_find_service( )
do_add_service( )
svcmgr_handler( )
三、Zygote进程启动
Zygote这个进程是非常重要的一个进程,Zygote进程的建立是真正的Android运行空间,初始化建立的Service都是Navtive service。
在脚本文件init.rc的描述
源码的位置为:frameworks\base\cmds\app_process\app_main.cpp
参数为:–zygote --start-system-server
接着就到了AndroidRuntime类了,代码调用了:
调用代码位置:Frameworks\base\core\jni\AndroidRuntime.cpp
再往下就调用了静态main函数
进入的代码位置为:frameworks\base\core\java\com\android\internal\os\ZygoteInit.java
Zygote就建立好了,利用Socket通讯,接收请求,Fork应用程序进程,进入Zygote进程服务框架中。
上述中的main函数,是在另外一个.so中,名为:libandroid_runtime.so,是一个共享库。在app_process加载的时候,就把这个.so编译进来了,看下面代码:
再看libandroid_runtime.so是在哪里编译出来的:Frameworks\base\core\jni\Android.mk,代码片段如下:
通过上面的共享库和资源加载preload(),整个虚拟机的资源都是共享的,当有fork出其他的虚拟机时候,就可以节省资源了,提高了效率!
四、SystemServer启动
在Zygote进程进入循环之前,调用了startSystemServer( )
调用代码位置:frameworks\base\core\java\com\android\internal\os\RuntimeInit.java
从startSystemServer开始执行并没有去调用SystemServer的任何方法,只是通过反射获取了main方法,付给了MethodAndArgsCaller,并抛出了MethodAndArgsCaller异常。
此异常是在哪里处理的呢?回到startSystemServer( )函数的调用处:在ZygoteInit的main函数中:
如果startSystemServer抛出了异常,跳过执行ZygoteInit进程的循环,这是怎么回事呢?
在startSystemServer中异常是由handleSystemServerProcess抛出。
MethodAndArgsCaller run函数:调用前面所提到的
//SystemServer main方法
m = cl.getMethod(“main”, new Class[] { String[].class });
启动了进程SystemServer。
init1代码位置为:frameworks\base\services\jni\com_android_server_SystemServer.cpp
在systme_init()中有调用:init2
再回到init2
在类ServerThread启动了大量的服务,可以仔细看看有哪些服务;关键可以到到这些:
一切就绪,只差Home启动界面!
五、Home启动
在systemReady中调用了下面函数:
看下面代码重点:
//Launcher
然后就启动了Home界面,完成了整个Android启动流程。
六、附件
整个流程如下:
ps查看开机启动的进程:(看看pid和ppid的关系)
觉得本文对您有用,麻烦点赞、关注、收藏,您的肯定是我创作的无限动力,谢谢!!!
这篇关于Android 系统启动流程源码分析的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!