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的关系)

在这里插入图片描述
在这里插入图片描述在这里插入图片描述

觉得本文对您有用,麻烦点赞、关注、收藏,您的肯定是我创作的无限动力,谢谢!!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/685431.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

EDA(四)Verilog

EDA(四)Verilog Verilog是一种用于电子系统设计自动化(EDA)的硬件描述语言(HDL),主要用于设计和模拟电子系统,特别是在集成电路(IC)和印刷电路板(…

教你解决PUBG绝地求生打完一把游戏无法返回大厅的问题

《绝地求生》(PUBG)作为风靡全球的战术竞技大作,凭借其高度还原的战场氛围和扣人心弦的生存挑战吸引了大量游戏玩家。不过,部分玩家在经历了一场紧张激烈的比赛后,遭遇了一个小困扰:游戏未能顺畅过渡到结算…

C++数据结构——AVL树

前言:本篇文章将紧随二叉搜索树的节奏,分享一个新的数据结构——AVL树。 目录 一.AVL树概念 二.AVL树插入规则 三.AVL树实现 1.基本框架 2.插入 3.旋转 1)左\右单旋 2)左右/右左双旋 4.遍历 5.求树高度 6.判断平衡 7.…

word转pdf的java实现(documents4j)

一、多余的话 java实现word转pdf可用的jar包不多,很多都是收费的。最近发现com.documents4j挺好用的,它支持在本机转换,也支持远程服务转换。但它依赖于微软的office。电脑需要安装office才能转换。鉴于没在linux中使用office,本…

PTP 对时协议 IEEE1588 网络对时 硬件基础

前言 在很多应用场景有精确对时的需求,例如车载网络,音视频流,工业网络。本文档将会阐述对时的硬件需求,网卡硬件以 Synopsys DesignWare Cores Ethernet MAC QoS 为例来展开说明。 协议 流行的协议为 IEEE1588 标准指定的对时…

Django 静态文件管理与部署指南

title: Django 静态文件管理与部署指南 date: 2024/5/10 17:38:36 updated: 2024/5/10 17:38:36 categories: 后端开发 tags: WebOptCDN加速DjangoCompressWebpackStaticDeployCICD-ToolsSecStatic 第一章:介绍 Django 静态文件的概念和重要性 在 Web 开发中&a…

爆爽,英语小白怒刷 50 课!像玩游戏一样学习英语~

重点!!!(先看这) 清楚自己学英语的目的, 先搞清楚目标,再行动自身现在最需要的东西:词汇量?口语?还是阅读能力?找对应的书籍,学习资料往兴趣靠拢:网上有大量的推荐美剧学习、小说学习,不要被他…

技术创作者在千帆AppBuilder中获得的极致体验

目录 前言 千帆AppBuilder简介 传统的技术文章写作方式 借助千帆AppBuilder提高写作质量和效率 千帆AppBuilder详细搭建步骤 1、注册百度智能云账号 2、登录百度智能云控制台 3、创建千帆AppBuilder应用 4、配置千帆AppBuilder应用 5、调试和发布千帆AppBuilder应用 …

你写的每条SQL都是全表扫描吗

你写的每条SQL都是全表扫描吗?如果是,那MySQL可太感谢你了,每一次SQL执行都是在给MySQL上压力、上对抗。MySQL有苦难言:你不知道索引吗?你写的SQL索引都失效了不知道吗?慢查询不懂啊?建那么多索…

Dependencies:查找项目中dll关联文件是否缺失。

前言 Dependencies工具作为一款优秀的DLL解析工具,能让你很直观地看到DLL的相关信息,如具备哪些功能函数、参数,又比如该DLL基于哪些DLL运行。判断该dll基于哪些dll运行,如果基于的dll丢失,那么就会提示。就能判断缺少…

Docker笔记(七)使用Docker部署Spring Boot项目

本文介绍如何使用Docker打包并部署Spring Boot多模块项目。 其中本文涉及的Docker的私库是用Nexus3搭建的。 使用Docker部署Spring Boot项目有三种方式 (1)使用 spring-boot-maven-plugin内置的build-image. (2)使用 Google 的 j…

手把手系列!使用 Zilliz Cloud 和 AWS Bedrock 搭建 RAG 应用

检索增强生成(Retrieval Augemented Generation, RAG)是一种 AI 框架,它通过结合信息检索和自然语言处理(NLP)能力从而增强文本生成。具体而言,RAG 系统中的语言模型通过一种检索机制查询和搜索知识库或外部…