Android 系统启动流程源码分析

2024-05-08 09:52

本文主要是介绍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 系统启动流程源码分析的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/970001

相关文章

Linux流媒体服务器部署流程

《Linux流媒体服务器部署流程》文章详细介绍了流媒体服务器的部署步骤,包括更新系统、安装依赖组件、编译安装Nginx和RTMP模块、配置Nginx和FFmpeg,以及测试流媒体服务器的搭建... 目录流媒体服务器部署部署安装1.更新系统2.安装依赖组件3.解压4.编译安装(添加RTMP和openssl模块

Android 悬浮窗开发示例((动态权限请求 | 前台服务和通知 | 悬浮窗创建 )

《Android悬浮窗开发示例((动态权限请求|前台服务和通知|悬浮窗创建)》本文介绍了Android悬浮窗的实现效果,包括动态权限请求、前台服务和通知的使用,悬浮窗权限需要动态申请并引导... 目录一、悬浮窗 动态权限请求1、动态请求权限2、悬浮窗权限说明3、检查动态权限4、申请动态权限5、权限设置完毕后

Springboot中分析SQL性能的两种方式详解

《Springboot中分析SQL性能的两种方式详解》文章介绍了SQL性能分析的两种方式:MyBatis-Plus性能分析插件和p6spy框架,MyBatis-Plus插件配置简单,适用于开发和测试环... 目录SQL性能分析的两种方式:功能介绍实现方式:实现步骤:SQL性能分析的两种方式:功能介绍记录

0基础租个硬件玩deepseek,蓝耘元生代智算云|本地部署DeepSeek R1模型的操作流程

《0基础租个硬件玩deepseek,蓝耘元生代智算云|本地部署DeepSeekR1模型的操作流程》DeepSeekR1模型凭借其强大的自然语言处理能力,在未来具有广阔的应用前景,有望在多个领域发... 目录0基础租个硬件玩deepseek,蓝耘元生代智算云|本地部署DeepSeek R1模型,3步搞定一个应

Android里面的Service种类以及启动方式

《Android里面的Service种类以及启动方式》Android中的Service分为前台服务和后台服务,前台服务需要亮身份牌并显示通知,后台服务则有启动方式选择,包括startService和b... 目录一句话总结:一、Service 的两种类型:1. 前台服务(必须亮身份牌)2. 后台服务(偷偷干

最长公共子序列问题的深度分析与Java实现方式

《最长公共子序列问题的深度分析与Java实现方式》本文详细介绍了最长公共子序列(LCS)问题,包括其概念、暴力解法、动态规划解法,并提供了Java代码实现,暴力解法虽然简单,但在大数据处理中效率较低,... 目录最长公共子序列问题概述问题理解与示例分析暴力解法思路与示例代码动态规划解法DP 表的构建与意义动

springboot启动流程过程

《springboot启动流程过程》SpringBoot简化了Spring框架的使用,通过创建`SpringApplication`对象,判断应用类型并设置初始化器和监听器,在`run`方法中,读取配... 目录springboot启动流程springboot程序启动入口1.创建SpringApplicat

通过prometheus监控Tomcat运行状态的操作流程

《通过prometheus监控Tomcat运行状态的操作流程》文章介绍了如何安装和配置Tomcat,并使用Prometheus和TomcatExporter来监控Tomcat的运行状态,文章详细讲解了... 目录Tomcat安装配置以及prometheus监控Tomcat一. 安装并配置tomcat1、安装

MySQL的cpu使用率100%的问题排查流程

《MySQL的cpu使用率100%的问题排查流程》线上mysql服务器经常性出现cpu使用率100%的告警,因此本文整理一下排查该问题的常规流程,文中通过代码示例讲解的非常详细,对大家的学习或工作有一... 目录1. 确认CPU占用来源2. 实时分析mysql活动3. 分析慢查询与执行计划4. 检查索引与表

C#使用DeepSeek API实现自然语言处理,文本分类和情感分析

《C#使用DeepSeekAPI实现自然语言处理,文本分类和情感分析》在C#中使用DeepSeekAPI可以实现多种功能,例如自然语言处理、文本分类、情感分析等,本文主要为大家介绍了具体实现步骤,... 目录准备工作文本生成文本分类问答系统代码生成翻译功能文本摘要文本校对图像描述生成总结在C#中使用Deep