android系统启动流程- ServiceManager进程启动流程
*注:基于Android11源码
ServiceManager进程是在init进程创建的,所以我们从init进程的main()开始分析:
// 文件路径: system/core/init/main.cpp
int main(int argc, char** argv) {
...
if (!strcmp(argv[1], "second_stage")) { //TODO 根据条件会走到这个分支
return SecondStageMain(argc, argv);
}
}
int SecondStageMain(int argc, char** argv) {
...
//用来存放解析出的内容
ActionManager& am = ActionManager::GetInstance();
ServiceList& sm = ServiceList::GetInstance();
//在这个方法中会对 /system/core/rootdir/init.rc 脚本文件文件进行解析
LoadBootScripts(am, sm);
//循环处理init.rc脚本中的command命令,处理完就进入等待
while (true) {
if (!(prop_waiter_state.MightBeWaiting() || Service::is_exec_service_running()))
{
//内部遍历执行每个action中携带的command对应的执行函数
am.ExecuteOneCommand();
}
}
}
static void LoadBootScripts(ActionManager& action_manager, ServiceList& service_list) {
//创建解析器
Parser parser = CreateParser(action_manager, service_list);
std::string bootscript = GetProperty("ro.boot.init_rc", "");
if (bootscript.empty()) {
//解析init.rc ,这个是手机设备上的路径,和源码中system/core/init/init.rc是一个文件
parser.ParseConfig("/system/etc/init/hw/init.rc");
if (!parser.ParseConfig("/system/etc/init")) {
late_import_paths.emplace_back("/system/etc/init");
}
// late_import is available only in Q and earlier release. As we don't
// have system_ext in those versions, skip late_import for system_ext.
parser.ParseConfig("/system_ext/etc/init");
if (!parser.ParseConfig("/product/etc/init")) {
late_import_paths.emplace_back("/product/etc/init");
}
if (!parser.ParseConfig("/odm/etc/init")) {
late_import_paths.emplace_back("/odm/etc/init");
}
if (!parser.ParseConfig("/vendor/etc/init")) {
late_import_paths.emplace_back("/vendor/etc/init");
}
} else {
parser.ParseConfig(bootscript);
}
}
下面是init.rc中启动servicemanager进程相关的部分:
on init
# Start essential services.
start servicemanager #启动servicemanager进程
start hwservicemanager
start vndservicemanager
有关servicemanager进程启动的细节配置被放在了 frameworks\native\cmds\servicemanager\servicemanager.rc
#此脚本文件描述了启动servicemanager进程时的一些细节
#service用于通知init进程创建名为servicemanager的进程,这个进程执行程序的路径是/system/bin/servicemanager
#在手机系统中是能找到这个文件的
service servicemanager /system/bin/servicemanager
class core animation
#表明此进程是以system身份运行的
user system
group system readproc
#说明servicemanager是系统中的关键服务,关键服务是不会退出的,若退出系统则会重启,系统重启则会重启
#以下onrestart修饰的进程,也可以说明这些进程是依赖于servicemanager进程的
critical
onrestart restart healthd
onrestart restart zygote
onrestart restart audioserver
onrestart restart media
onrestart restart surfaceflinger
onrestart restart inputflinger
onrestart restart drm
onrestart restart cameraserver
onrestart restart keystore
onrestart restart gatekeeperd
onrestart restart thermalservice
writepid /dev/cpuset/system-background/tasks
shutdown critical
当执行到 start servicemanager 这条命令,就会运行android设备(比如手机)中 /system/bin/servicemanager这个可执行文件,而这个可执行程序就是servicemanager进程,他由 frameworks\native\cmds\servicemanager\main.cpp 文件编译生成的。什么?你不信?打开frameworks\native\cmds\servicemanager\Android.bp,这就是证据:
...
# cc_binary表示编译成一个二进制文件
cc_binary {
name: "servicemanager", #文件名
defaults: ["servicemanager_defaults"],
init_rc: ["servicemanager.rc"], #配置详情
srcs: ["main.cpp"], #要编译的源文件
}
...
这样我们就知道运行servicemanager这个可执行文件就是运行到了frameworks\native\cmds\servicemanager\main.cpp这个文件了。
int main(int argc, char** argv) {
if (argc > 2) {
LOG(FATAL) << "usage: " << argv[0] << " [binder driver]";
}
//此时要使用的binder驱动为 "/dev/binder",同样这个路径也是android设备上的路径
const char* driver = argc == 2 ? argv[1] : "/dev/binder";
//打开binder驱动文件并将此进程与binder驱动进行内存映射,ProcessState是用来保存进程状态的一个类
sp<ProcessState> ps = ProcessState::initWithDriver(driver); //注释1
//设置最大线程数
ps->setThreadPoolMaxThreadCount(0);
ps->setCallRestriction(ProcessState::CallRestriction::FATAL_IF_NOT_ONEWAY);
//实例化ServiceManager
sp<ServiceManager> manager = new ServiceManager(std::make_unique<Access>());
//将自身作为服务添加
if (!manager->addService("manager", manager, false /*allowIsolated*/, IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk()) {
LOG(ERROR) << "Could not self register servicemanager";
}
//创建服务端Bbinder对象
IPCThreadState::self()->setTheContextObject(manager); //注释2
//设置称为binder驱动的context manager,称为上下文的管理者
ps->becomeContextManager(nullptr, nullptr);
//通过Looper epoll机制处理binder事务
sp<Looper> looper = Looper::prepare(false /*allowNonCallbacks*/);
//Binder驱动中数据变化的监听
BinderCallback::setupTo(looper); //注释3
ClientCallbackCallback::setupTo(looper, manager);
while(true) {
looper->pollAll(-1);
}
// should not be reached
return EXIT_FAILURE;
}
先看注释1:
//frameworks\native\libs\binder\ProcessState.cpp
sp<ProcessState> ProcessState::initWithDriver(const char* driver)
{
Mutex::Autolock _l(gProcessMutex);
if (gProcess != nullptr) {
// Allow for initWithDriver to be called repeatedly with the same
// driver. 允许使用同一驱动程序重复调用initWithDriver()
if (!strcmp(gProcess->getDriverName().c_str(), driver)) {//若当前ProcessState对象的驱动与传参不同
return gProcess; //直接返回现有的ProcessState对象
}
LOG_ALWAYS_FATAL("ProcessState was already initialized.");
}
if (access(driver, R_OK) == -1) {
ALOGE("Binder driver %s is unavailable. Using /dev/binder instead.", driver);
driver = "/dev/binder";
}
//第一次调用gProcess为空,走这里
gProcess = new ProcessState(driver); //创建新对象
return gProcess;
}
//ProcessState类的构造函数
ProcessState::ProcessState(const char *driver)
: mDriverName(String8(driver)) //以下都是成员变量初始化赋值,设置驱动名
, mDriverFD(open_driver(driver)) //打开驱动文件,拿到驱动文件的文件描述符
, mVMStart(MAP_FAILED)
, mThreadCountLock(PTHREAD_MUTEX_INITIALIZER)
, mThreadCountDecrement(PTHREAD_COND_INITIALIZER)
, mExecutingThreadsCount(0)
, mMaxThreads(DEFAULT_MAX_BINDER_THREADS)
, mStarvationStartTimeMs(0)
, mBinderContextCheckFunc(nullptr)
, mBinderContextUserData(nullptr)
, mThreadPoolStarted(false)
, mThreadPoolSeq(1)
, mCallRestriction(CallRestriction::NONE)
{
if (mDriverFD >= 0) { //大于0,说明打开binder驱动成功
// mmap内存映射,提供一块虚拟地址空间来接收事务(即从客户端发送的请求(数据))。
// BINDER_VM_SIZE 地址空间大小BINDER_VM_SIZE = 1M - 8k
mVMStart = mmap(nullptr, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);
if (mVMStart == MAP_FAILED) {//映射失败
// *sigh*
ALOGE("Using %s failed: unable to mmap transaction memory.\n", mDriverName.c_str());
close(mDriverFD);
mDriverFD = -1;
mDriverName.clear();
}
}
...
}
static int open_driver(const char *driver)
{
//得到驱动的文件描述符
int fd = open(driver, O_RDWR | O_CLOEXEC);
if (fd >= 0) {
int vers = 0;
//binder驱动版本检查
status_t result = ioctl(fd, BINDER_VERSION, &vers);
if (result == -1) {
ALOGE("Binder ioctl to obtain version failed: %s", strerror(errno));
close(fd);
fd = -1;
}
if (result != 0 || vers != BINDER_CURRENT_PROTOCOL_VERSION) {
ALOGE("Binder driver protocol(%d) does not match user space protocol(%d)! ioctl() return value: %d",
vers, BINDER_CURRENT_PROTOCOL_VERSION, result);
close(fd);
fd = -1;
}
size_t maxThreads = DEFAULT_MAX_BINDER_THREADS;
//给驱动设置最大线程数
result = ioctl(fd, BINDER_SET_MAX_THREADS, &maxThreads);
if (result == -1) {
ALOGE("Binder ioctl to set max threads failed: %s", strerror(errno));
}
} else {
ALOGW("Opening '%s' failed: %s\n", driver, strerror(errno));
}
return fd;
}
接下来到注释2部分:
// frameworks\native\libs\binder\IPCThreadState.cpp
//IPCThreadState是线程单例
IPCThreadState* IPCThreadState::self()
{
//不是初次调用的情况,TLS的全称为Thread Local Storage
if (gHaveTLS.load(std::memory_order_acquire)) {
restart:
//初次调用,生成线程私有变量key后
//TLS 表示线程本地存储空间,和java中的ThreadLocal是一个意思
const pthread_key_t k = gTLS;
IPCThreadState* st = (IPCThreadState*)pthread_getspecific(k);
if (st) return st;
//没有的话就实例化一个
return new IPCThreadState;
}
// Racey, heuristic test for simultaneous shutdown.
// IPCThreadState shutdown后不能再获取
if (gShutdown.load(std::memory_order_relaxed)) {
ALOGW("Calling IPCThreadState::self() during shutdown is dangerous, expect a crash.\n");
return nullptr;
}
// 首次获取时gHaveTLS为false,会先走这里
pthread_mutex_lock(&gTLSMutex);
if (!gHaveTLS.load(std::memory_order_relaxed)) {
//创建一个key,作为存放线程本地变量的key
int key_create_value = pthread_key_create(&gTLS, threadDestructor);
if (key_create_value != 0) {
pthread_mutex_unlock(&gTLSMutex);
ALOGW("IPCThreadState::self() unable to create TLS key, expect a crash: %s\n",
strerror(key_create_value));
return nullptr;
}
//创建完毕,gHaveTLS设置为true
gHaveTLS.store(true, std::memory_order_release);
}
pthread_mutex_unlock(&gTLSMutex);
// 回到gHaveTLS为true的case
goto restart;
}
sp<BBinder> the_context_object;
void IPCThreadState::setTheContextObject(sp<BBinder> obj)
{
//赋值给一个BBinder类型的成员变量,即传进来的这个manager就是服务端的BBinder
the_context_object = obj;
}
为了更好的理解ServiceManager这个类,下面是一张它的继承关系图:

下面来到注释3:
static sp<BinderCallback> setupTo(const sp<Looper>& looper) {
sp<BinderCallback> cb = new BinderCallback;
int binder_fd = -1;
//向binder驱动发送BC_ENTER_LOOPER事务请求,并获得binder驱动的文件描述符
IPCThreadState::self()->setupPolling(&binder_fd);
LOG_ALWAYS_FATAL_IF(binder_fd < 0, "Failed to setupPolling: %d", binder_fd);
// Flush after setupPolling(), to make sure the binder driver
// knows about this thread handling commands.
// 检查写缓存是否有可写数据,有的话发给binder驱动
IPCThreadState::self()->flushCommands();
// 监听binder文件描述符
int ret = looper->addFd(binder_fd,
Looper::POLL_CALLBACK,
Looper::EVENT_INPUT,
cb,
nullptr /*data*/);
LOG_ALWAYS_FATAL_IF(ret != 1, "Failed to add binder FD to Looper");
return cb;
}
// 当binder驱动发来消息后,就可以通过次函数接收处理了
int handleEvent(int /* fd */, int /* events */, void* /* data */) override {
//处理消息
IPCThreadState::self()->handlePolledCommands();
return 1; // Continue receiving callbacks.
}
};
servicemanager进程启动过程中,主要做了以下四件事:
1)初始化binder驱动
2)将自身以“manager” 添加到servicemanager中的map集合中
3)注册成为binder驱动的上下问管理者
- 给Looper设置callback,进入无限循环,处理client端发来的请求
总结:
1.ServiceManager是一个独立的进程,由init进程创建,且在创建zygote进程之前被创建。
2.IBinder是什么?它是实现了AIDL接口的实体类,它实现了接口中的所有方法。
android系统启动流程- ServiceManager进程启动流程的更多相关文章
- ORACLE11G R2 RAC的进程启动流程
简要说明ORACLE11GR2 RAC的进程启动流程: 1.启动流程概览图: 二.RAC启动流程的梳理: 第一层:OHASD 启动:(OHASD派生) 1.CSSDAGENT负责启动CSSD的AGEN ...
- Android Activity启动流程, app启动流程,APK打包流程, APK安装过程
1.Activity启动流程 (7.0版本之前) 从startActivity()开始,最终都会调用startActivityForResult() 在该方法里面会调用Instrumentation. ...
- broadcom代码中httpd进程启动流程介绍
Broadcom代码中包含WEB配置管理媒介, 在嵌入式WEB服务器min_httpd基础上改造实现, 其bin名称为httpd,此httpd可以由管理进程有连接后动态启动,并且当一段时间内没有连接到 ...
- Chromium的GPU进程启动流程
转载请注明出处:http://www.cnblogs.com/fangkm/p/3960327.html 硬件渲染依赖计算机的GPU,GPU种类繁多,兼容这么多种类的硬件,稳定性是个大问题,虽然Chr ...
- ARM-Linux移植之(三)——init进程启动流程分析
我们通常使用Busybox来构建根文件系统的必要的应用程序.Busybox通过传入的参数来决定执行何种操作.当init进程启动时,实际上调用的是Busybox的init_main()函数,下面我们来分 ...
- Android的Launcher启动流程 “Launcher部分启动流程”
研究代码从:AndroidManifest.xml.自定义的Application.java开始. Android系统启动时,系统需要一个Home应用程序来负责将这些应用程序展示出来:也就是该应用的目 ...
- Android四大组件与进程启动的关系(转)
一. 概述 Android系统将进程做得很友好的封装,对于上层app开发者来说进程几乎是透明的. 了解Android的朋友,一定知道Android四大组件,但对于进程可能会相对较陌生. 一个进程里面可 ...
- 【Chromium】GPU进程启动流程
本篇文档以gpu进程的创建和启动为例,讲述chormium如何启动一个browser进程的子进程 PS:本文使用的chromium代码版本为71 前言 GPU进程的启动时机是由browser进程负责的 ...
- Android系统开机启动流程及init进程浅析
Android系统启动概述 Android系统开机流程基于Linux系统,总体可分为三个阶段: Boot Loader引导程序启动Linux内核启动Android系统启动,Launcher/app启动 ...
- Tiny4412 Android 启动流程
Android系统的启动主要包括三个阶段: ①BootLoader启动 ②Linux Kernel启动 ③Android系统启动 前面我们大致分析了前面两个步骤,即u-boot和内核的启动流程(内核启 ...
随机推荐
- DP进阶合集
(ps:本集合为Star_F总结的dp进阶知识,持续更新~. 转载本文章需要联系我,否则视为侵权!!) 前置知识:线性dp,背包,树形dp,区间dp 内容预览: 状压dp 数位dp dp优化(前缀和, ...
- 第零讲:基础架构:一条SQL查询语句是如何执行的
目录 第零讲:基础架构:一条SQL查询语句是如何执行的 正确的认识事物的方式方法(极为重要): sql语句内部的执行过程:(极为重要) MySQL 可以分为 Server 层和存储引擎层两部分. Se ...
- 什么是智慧城市(Smart City)?
Smart City是一个常见的概念,但是这个东西,这个名词到底指代的是什么却一直搞不太清,于是就查了查资料,有了这篇blog. 参考: https://baijiahao.baidu.com/s?i ...
- jax框架的官方编译版本 —— 预编译发行版本(release 列表)
jax框架的Google官方给出的预编译版本,支持CUDA和CUDNN的,带有python版本号,CUDA版本号,CUDNN版本号的: https://storage.googleapis.com/j ...
- 证明: 设n阶方阵A相似于对角阵Λ, λ是A的k重特征值, 则r(λE-A)=n-k.
命题: 设n阶方阵A相似于对角阵Λ, λ是A的k重特征值, 则r(λE-A)=n-k.证明: 由定理3.9: A~Λ <=> A有n个线性无关的特征向量, 知k重特征值λ存在k个线性无关的 ...
- .NET 免费开源工业物联网网关
前言 IoTClient 是一个针对物联网 (IoT) 领域的开源客户端库,它主要用于实现与各种工业设备之间的通信.这个库是用 C# 编写的,并且基于 .NET Standard 2.0,这意味着可以 ...
- UE Websocket 通信
项目中遇到UE需要对接Websocket协议接收实时数据. 所以需要实现一个Websocket Client的功能. 由于UE引擎已经集成了Websocket库(基于libwebsocket),可以通 ...
- 【安装部署】Apache SeaTunnel 和 Web快速安装详解
版本说明 由于作者目前接触当前最新版本为2.3.4 但是官方提供的web版本未1.0.0,不兼容2.3.4,因此这里仍然使用2.3.3版本. 可以自定义兼容处理,官方提供了文档:https://mp. ...
- 秒懂全文:盘点13个各具特色的AI智能阅读助手工具
在当今信息爆炸的时代,AI阅读工具正在革新我们的阅读方式,成为了提高效率.优化阅读体验的关键. 这类AI阅读辅助工具,只需要上传文件或者输入链接,便可以直接以聊天对话的形式进行一键总结和智能问答,满足 ...
- PLC开发没有前景想转行嵌入式,找个培训机构还是自学?
0. 粉丝提问 把粉丝的情况和问题总结起来,主要以下几点: 这位粉丝19年毕业,25岁,专业是是自动化,之前从事plc开发,现在在自学单片机,想转行做Linux相关开发 犹豫是自学还是报线下培训班? ...