[TOC]

概述

文章参考:https://blog.csdn.net/itachi85/article/details/104205274

上一篇文章Android进程间通信(IPC)机制Binder简要介绍和学习计划简要介绍了Android系统进程间通信机制Binder的总体架构,它由Client、Server、Service Manager和驱动程序Binder四个组件构成。

本文着重介绍组件Service Manager,它是整个Binder机制的守护进程,用来管理开发者创建的各种Server,并且向Client提供查询Server远程接口的功能。ServiceManager本身也是一个Binder服务,但并没有采用libbinder中的多线程模型来与Binder驱动通信,而是自行编写了binder.c直接和Binder驱动来通信,并且只有一个循环binder_loop来进行读取和处理事务,这样的好处是简单而高效。

既然Service Manager组件是用来管理Server并且向Client提供查询Server远程接口的功能,那么,Service Manager就必然要和Server以及Client进行通信了。我们知道,ServiceManger、Client和Server三者分别是运行在独立的进程当中,这样它们之间的通信也属于进程间通信了,而且也是采用Binder机制进行进程间通信,因此,Service Manager在充当Binder机制的守护进程的角色的同时,也在充当Server的角色,然而,它是一种特殊的Server,下面我们将会看到它的特殊之处。

与Service Manager相关的源代码较多,这里不会完整去分析每一行代码,主要是带着Service Manager是如何成为整个Binder机制中的守护进程这条主线来一步一步地深入分析相关源代码,包括从用户空间到内核空间的相关源代码。

ServiceManager的启动

ServiceManager是init进程负责启动的,具体是在解析init.rc配置文件时启动的,init进程是在系统启动时启动的,因此ServiceManager亦是如此。

1
2
3
4
5
// 启动必不可少的服务
# Start essential services.
start servicemanager
start hwservicemanager
start vndservicemanager

rc文件内部由Android初始化语言编写(Android Init Language)编写的脚本,它主要包含五种类型语句:Action、Commands、Services、Options和Import。

在Android 7.0中对init.rc文件进行了拆分,每个服务一个rc文件。ServiceManager的启动脚本在servicemanager.rc中:
frameworks/native/cmds/servicemanager/servicemanager.rc

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/**
* 代码位于:frameworks/native/cmds/servicemanager/servicemanager.rc
**/
service servicemanager /system/bin/servicemanager // 表示这个servicemanager进程执行程序的路径为/system/bin/servicemanager
class core animation
user system // user说明servicemanager是以用户system的身份运行的
group system readproc
critical // critical说明servicemanager是系统中的关键服务,关键服务是不会退出的,如果退出了,系统就会重启
file /dev/kmsg w
onrestart setprop servicemanager.ready false
onrestart restart apexd
onrestart restart audioserver
onrestart restart gatekeeperd
onrestart class_restart --only-enabled main
onrestart class_restart --only-enabled hal
onrestart class_restart --only-enabled early_hal
task_profiles ServiceCapacityLow
shutdown critical

service用于通知init进程创建名为servicemanager的进程,这个servicemanager进程执行程序的路径为/system/bin/servicemanager。

注释1的关键字user说明servicemanager是以用户system的身份运行的,注释2处的critical说明servicemanager是系统中的关键服务,关键服务是不会退出的,如果退出了,系统就会重启,当系统重启时就会启动用onrestart关键字修饰的进程,比如zygote、media、surfaceflinger等等。

servicemanager的入口函数在service_manager.c中,具体的启动流程图如下:

我们看一下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
/**
* 代码位于:frameworks/native/cmds/servicemanager/main.cpp
* @brief 启动ServiceManager的main函数
*
* @param argc
* @param argv
* @return int
*/
int main(int argc, char** argv) {
android::base::InitLogging(argv, android::base::KernelLogger);

if (argc > 2) {
LOG(FATAL) << "usage: " << argv[0] << " [binder driver]";
}

const char* driver = argc == 2 ? argv[1] : "/dev/binder";

LOG(INFO) << "Starting sm instance on " << driver;

sp<ProcessState> ps = ProcessState::initWithDriver(driver);
ps->setThreadPoolMaxThreadCount(0);
ps->setCallRestriction(ProcessState::CallRestriction::FATAL_IF_NOT_ONEWAY);

sp<ServiceManager> manager = sp<ServiceManager>::make(std::make_unique<Access>());
if (!manager->addService("manager", manager, false /*allowIsolated*/, IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk()) {
LOG(ERROR) << "Could not self register servicemanager";
}

IPCThreadState::self()->setTheContextObject(manager);
ps->becomeContextManager();

sp<Looper> looper = Looper::prepare(false /*allowNonCallbacks*/);

BinderCallback::setupTo(looper);
ClientCallbackCallback::setupTo(looper, manager);

#ifndef VENDORSERVICEMANAGER
if (!SetProperty("servicemanager.ready", "true")) {
LOG(ERROR) << "Failed to set servicemanager ready property";
}
#endif

while(true) {
looper->pollAll(-1);
}

// should not be reached
return EXIT_FAILURE;
}

binder_state结构体用来存储binder的三个信息:

1
2
3
4
5
6
struct binder_state
{
int fd; //binder设备的文件描述符
void *mapped; //binder设备文件映射到进程的地址空间
size_t mapsize; //内存映射后,系统分配的地址空间的大小,默认为128KB
};