*注:基于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驱动的上下问管理者

  1. 给Looper设置callback,进入无限循环,处理client端发来的请求

总结:

1.ServiceManager是一个独立的进程,由init进程创建,且在创建zygote进程之前被创建。

2.IBinder是什么?它是实现了AIDL接口的实体类,它实现了接口中的所有方法。

android系统启动流程- ServiceManager进程启动流程的更多相关文章

  1. ORACLE11G R2 RAC的进程启动流程

    简要说明ORACLE11GR2 RAC的进程启动流程: 1.启动流程概览图: 二.RAC启动流程的梳理: 第一层:OHASD 启动:(OHASD派生) 1.CSSDAGENT负责启动CSSD的AGEN ...

  2. Android Activity启动流程, app启动流程,APK打包流程, APK安装过程

    1.Activity启动流程 (7.0版本之前) 从startActivity()开始,最终都会调用startActivityForResult() 在该方法里面会调用Instrumentation. ...

  3. broadcom代码中httpd进程启动流程介绍

    Broadcom代码中包含WEB配置管理媒介, 在嵌入式WEB服务器min_httpd基础上改造实现, 其bin名称为httpd,此httpd可以由管理进程有连接后动态启动,并且当一段时间内没有连接到 ...

  4. Chromium的GPU进程启动流程

    转载请注明出处:http://www.cnblogs.com/fangkm/p/3960327.html 硬件渲染依赖计算机的GPU,GPU种类繁多,兼容这么多种类的硬件,稳定性是个大问题,虽然Chr ...

  5. ARM-Linux移植之(三)——init进程启动流程分析

    我们通常使用Busybox来构建根文件系统的必要的应用程序.Busybox通过传入的参数来决定执行何种操作.当init进程启动时,实际上调用的是Busybox的init_main()函数,下面我们来分 ...

  6. Android的Launcher启动流程 “Launcher部分启动流程”

    研究代码从:AndroidManifest.xml.自定义的Application.java开始. Android系统启动时,系统需要一个Home应用程序来负责将这些应用程序展示出来:也就是该应用的目 ...

  7. Android四大组件与进程启动的关系(转)

    一. 概述 Android系统将进程做得很友好的封装,对于上层app开发者来说进程几乎是透明的. 了解Android的朋友,一定知道Android四大组件,但对于进程可能会相对较陌生. 一个进程里面可 ...

  8. 【Chromium】GPU进程启动流程

    本篇文档以gpu进程的创建和启动为例,讲述chormium如何启动一个browser进程的子进程 PS:本文使用的chromium代码版本为71 前言 GPU进程的启动时机是由browser进程负责的 ...

  9. Android系统开机启动流程及init进程浅析

    Android系统启动概述 Android系统开机流程基于Linux系统,总体可分为三个阶段: Boot Loader引导程序启动Linux内核启动Android系统启动,Launcher/app启动 ...

  10. Tiny4412 Android 启动流程

    Android系统的启动主要包括三个阶段: ①BootLoader启动 ②Linux Kernel启动 ③Android系统启动 前面我们大致分析了前面两个步骤,即u-boot和内核的启动流程(内核启 ...

随机推荐

  1. 自制基于simplefoc大功率驱动板想法的由来,同时欢迎有相同兴趣的F友一起来玩。。。

    前一阵子,偶然在B站上看了一个simplefoc的介绍视频,代码简洁.算法精妙让人佩服,更让人佩服的是:开源!遂!搜索之!不搜不知道一搜吓一跳,发现太OUT了,原来玩这个算法的人这么多,让我这个整天沉 ...

  2. 【Vue】使用iframe解决多应用整合问题(微前端)

    一.需求背景 有老系统需要重构,新做的系统需要做一个大一统的整合,类似一个分类栏目 在菜单位置罗列出有什么子系统应用,点击对应的应用菜单,展示区跳转到相应的子系统应用中 我用Excel简单描述了下系统 ...

  3. 【Vue】Re11 Vue 与 Webpack

    一.案例环境前置准备: 创建一个空目录用于案例演示 mkdir vue-sample 初始化案例和安装webpack cd vue-sample npm install webpack@3.6.0 - ...

  4. 【FastDFS】环境搭建 02 测试

    自带工具测试: 编辑客户端配置文件: vim client.conf 配置完成后,随便上传一个图片到root目录下 运行FastFDS文件上传程序,并将客户端配置文件作为加载参数1,要上传的图片文件位 ...

  5. 【转载】 推荐算法之Thompson(汤普森)采样

    原文地址: https://www.cnblogs.com/gczr/p/11220187.html ------------------------------------------------- ...

  6. 祝贺小鹏汽车Gallardot同学成为Apache DolphinScheduler Committer!

    社区迎来新committer!这次是来自小鹏汽车的Gallardot,看看他与Apache DolphinScheduler社区的故事吧. 对话社区 Q1:您为Apache DolphinSchedu ...

  7. 微服务全链路跟踪:jaeger集成hystrix

    微服务全链路跟踪:grpc集成zipkin 微服务全链路跟踪:grpc集成jaeger 微服务全链路跟踪:springcloud集成jaeger 微服务全链路跟踪:jaeger集成istio,并兼容u ...

  8. java增量发布工具

    有些公司由于没有使用maven作为构建工具,全量发布时没问题,而修改bug增量发布往往是将改动的代码手动编译后,从classes目录下拷贝到jar中然后再放到tomcat目录下发布,这种方法准确度不高 ...

  9. java本地增量打包工具

    在打增量包每次都需要将class文件.jsp文件等拷贝到增量包中比较麻烦.所以就写了一个增量打包工具. 工作原理:根据文件的最后修改时间来打增量. 1.查找Java类增量:根据eclipse工程下的. ...

  10. 从头搭建一个嵌入式web服务器-boa服务器

    一.什么是boa? BOA是一款非常小巧的Web服务器,源代码开放.性能优秀.支持CGI通用网关接口技术,特别适合应用在嵌入式系统中. BOA服务器主要功能是在互联嵌入式设备之间进行信息交互,达到通过 ...