[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亦是如此。
| 12
 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
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 
 | 
 
 service servicemanager /system/bin/servicemanager
 class core animation
 user system
 group system readproc
 critical
 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中,具体的启动流程图如下:
我们看一下代码:
| 12
 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
 
 | 
 
 
 
 
 
 
 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 , 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 );
 
 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);
 }
 
 
 return EXIT_FAILURE;
 }
 
 | 
binder_state结构体用来存储binder的三个信息:
| 12
 3
 4
 5
 6
 
 | struct binder_state{
 int fd; //binder设备的文件描述符
 void *mapped; //binder设备文件映射到进程的地址空间
 size_t mapsize; //内存映射后,系统分配的地址空间的大小,默认为128KB
 };
 
 |