一、概述
本文将分析系统服务的注册流程,如注册ActivityManagerService时,通过ServiceManager中的静态方法addService注册具体的服务。ServiceManger是Binder IPC通信过程中的守护进程,是一个具体的服务,其功能主要是查询和注册服务。
二、ServiceManager启动
ServiceManager是由init进程通过servicemanager.rc文件而创建,其所在的可执行文件在system/bin/servicemanager,对应的源文件是service_manager.c。
1 | service servicemanager /system/bin/servicemanager |
启动ServiceManager的入口时文件中的main方法.
2.1 mian
[->service_manager.c]
1 | int main(int argc, char** argv) |
2.2 binder_open
[->servicemanager/binder.c]
1 | struct binder_state *binder_open(const char* driver, size_t mapsize) |
调用open打开binder驱动设备,open方法经过系统调用,进入binder驱动,然后调用binder_open方法,该方法会在binder驱动层创建一个binder_proc对象,再将binder_proc对象赋值给fd->private_data,同时放入全局链表binder_procs。
再通过ioctl检查当前binder版本与binder驱动层的版本是否一致。
调用mmap进行内存映射,通过系统调用,对应于binder驱动层的binder_mmap方法,该方法会在binder驱动层创建Binder_buffer对象,并放入当前的binder_proc的proc->buffers链表。
2.3 binder_become_context_manager
[->servicemanager/binder.c]
1 | int binder_become_context_manager(struct binder_state *bs) |
成为上下文管理者,整个系统只有一个这样的管理者,经过系统调用binder驱动层的binder_ioctl方法。
2.4 binder_loop
[->servicemanager/binder.c]
1 | void binder_loop(struct binder_state *bs, binder_handler func) |
进入循环读写操作,main方法传递过来的参数fun指向svcmgr_handler。
三、注册服务
ServiceManager.addService(String name, IBinder service)过程
3.1 SM.addService
[->ServiceManager.java]
1 | public static void addService(String name, IBinder service) { |
3.2 getIServiceManager
[->ServiceManager.java]
1 | private static IServiceManager getIServiceManager() { |
getContextObject通过Native方式调用。
3.2.1 Binder.allowBlocking
1 | public static IBinder allowBlocking(IBinder binder) { |
这个方法用来判断IBinder类,根据不同情况添加标志,具体可见3.7节
3.2.2 getContextObject
[->android_util_Binder.cpp]
1 | static jobject android_os_BinderInternal_getContextObject(JNIEnv* env, jobject clazz) |
3.2.2.1 ProcessState::self
[->ProcessState.cpp]
1 | sp<ProcessState> ProcessState::self() |
单例模式创建ProcessState对象,其初始化如下:
1 | ProcessState::ProcessState(const char *driver) |
ProcessState一个进程只打开一个binder设置一次,其中mDriverFD,记录binder驱动的fd,用于访问binder设置;
BINDER_VM_SIZE = 1 1024 1024 - 4096 * 2),binder分配的内存大小为1M-8K;
DEFAULT_MAX_BINDER_THREADS =15,binder默认最大可并发访问的线程数为16。
打开驱动的过程如下,这里就只介绍到这里。
1 | static int open_driver(const char *driver) |
3.2.2.2 PS.getContextObject
[->ProcessState.cpp]
1 | sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& /*caller*/) |
3.2.2.3 PS.getStrongProxyForHandle
[->ProcessState.cpp]
1 | sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle) |
当handler值所对应的Binder不存在或弱引用无效时会创建BpBinder,否则直接获取。对应handler等于0的情况,通过PING_TRANSACTION来判断是否准备就绪。如果context manager还未生效前,一个BpBinder的本地已经被创建,那么驱动将无法提供context manager的引用。
3.2.3 javaObjectForIBinder
[->android_util_Binder.cpp]
1 | jobject javaObjectForIBinder(JNIEnv* env, const sp<IBinder>& val) |
根据BpBinder(C++)创建BinderProxy(java)对象,主要工作是创建BinderProxy对象。
ServiceManagerNative.asInterface(Binder.allowBlocking(BinderInternal.getContextObject()));相当于
ServiceManagerNative.asInterface(new BinderProxy())
3.3 SMN.asInterface
1 | static public IServiceManager asInterface(IBinder obj) |
由3.2节可知ServiceManagerNative.asInterface(new BinderProxy()),等价于
new ServiceManagerProxy(new BinderProxy());
3.3.1 ServiceManagerProxy
[->ServiceManagerNative::ServiceManagerProxy]
1 | class ServiceManagerProxy implements IServiceManager { |
mRemote为BinderProxy对象,该对象对应于BpBinder(0),作为binder代理类,执行native层ServiceManager
getIServiceManager()等价于new ServiceManagerProxy(new BinderProxy());
getIServiceManager().addService等价于ServiceManagerProxy.addService
framework层的ServiceManager的调用实际交给了ServiceManagerProxy成员变量BinderProxy,而BinderProxy通过JNI方式,最终调用的BpBinder对象,可以看出binder架构的核心功能依赖于native架构的服务来完成。
3.4 SMP.addService
[->ServiceManagerNative::ServiceManagerProxy]
1 | public void addService(String name, IBinder service, boolean allowIsolated, int dumpPriority) |
3.5 writeStrongBinder(Java)
[->Parcel.java]
1 | public final void writeStrongBinder(IBinder val) { |
3.5.1 android_os_Parcel_writeStrongBinder
[->android_os_Parcel.cpp]
1 | static void android_os_Parcel_writeStrongBinder(JNIEnv* env, jclass clazz, jlong nativePtr, jobject object) |
nativePtr为native层创建Parcel对象后返回的指针地址。
3.5.2 ibinderForJavaObject
[->android_util_Binder.cpp]
1 | sp<IBinder> ibinderForJavaObject(JNIEnv* env, jobject obj) |
根据Binder(Java)生成JavaBBinderHolder(C++)对象,并把JavaBBinderHolder对象地址保存到Binder.mObject成员变量
如果是BinderProxy(Java)返回的是Binder Native代理BpBinder。
3.5.3 JavaBBinderHolder
[->android_util_Binder.cpp]
1 | class JavaBBinderHolder |
3.5.4 new JavaBBinder
[->android_util_Binder.cpp]
1 | class JavaBBinder : public BBinder |
创建JavaBBinder,该类继承于BBinder, data.writeStrongBinder(service);等价于parcel->writeStrongBinder(new JavaBBinder(env, obj))
3.6 writeStrongBinder(C++)
[->Parcel.cpp]
1 | status_t Parcel::writeStrongBinder(const sp<IBinder>& val) |
3.6.1 flatten_binder
[->Parcel.cpp]
1 | status_t flatten_binder(const sp<ProcessState>& /*proc*/, |
主要是将Binder对象扁平化,转换成flat_binder_object。
对于Binder实体,cookie记录Binder实体的指针
对于Binder代理,则用handle记录Binder代理的句柄。
3.6.2 finish_flatten_binder
[->Parcel.cpp]
1 | inline static status_t finish_flatten_binder( |
回到3.4的addService过程,则进入transact过程
3.7 BP.transact
[->BinderProxy.java]
1 | public boolean transact(int code, Parcel data, Parcel reply, int flags) throws RemoteException { |
3.8 android_os_BinderProxy_transact
[->android_util_Binder.cpp]
1 | static jboolean android_os_BinderProxy_transact(JNIEnv* env, jobject obj, |
3.9 BpBinder::transact
[->BpBinder.cpp]
1 | status_t BpBinder::transact( |
3.9.1 BpBinder::transact
[->IPCThreadState.cpp]
1 | IPCThreadState* IPCThreadState::self() |
TLS(Thread local storage),线程本地存储空间,每个线程都有自己私有的TLS,线程之间不能共享。
pthread_setspecific/pthread_getspecific可以设置和获取这些空间中的内容。
3.9.2 new IPCThreadState
[->IPCThreadState.cpp]
1 | IPCThreadState::IPCThreadState() |
每个线程都有一个IPCThreadState,每个IPCThreadState都有一个mIn,mOut,成员变量mProcess保存了ProcessState变量,每个进程只有一个。
mInt用来接收来自Binder设备的数据,默认大小事256
mOut用来存储发往Binder设备的数据,默认大小事256
3.10 IPC::transact
[->IPCThreadState.cpp]
1 | status_t IPCThreadState::transact(int32_t handle, |
transact主要工作:
errorCheck错误检查
writeTransactionData传输数据
waitForResponse等待响应
3.11 IPC::writeTransactionData
[->IPCThreadState.cpp]
1 | status_t IPCThreadState::writeTransactionData(int32_t cmd, uint32_t binderFlags, |
handler对象用来标记目的端,注册服务的目的端为ServiceManager,这里handle = 0所对应的是binder实体对象。
binder_transaction_data是binder驱动通信的数据结构,该过程吧Binder请求码BC_TRANSACTION和binder_transaction_data结构体写入mOut,写完后执行waitForResponse方法。
binder_transaction_data中重要的成员变量
data_size,binder_transaction的数据大小
data.ptr.buffer,binder_transaction数据的起始地址
offsets_size,记录flat_binder_object结构体的个数
data.ptr.offsets,记录flat_binder_object结构体的数据偏移量
3.12 IPC::waitForResponse
[->IPCThreadState.cpp]
1 | status_t IPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult) |
talkWithDriver过程是和binder驱动通信过程,Binder驱动收到BC_TRANSACTION后,会回应BR_TRANSACTION_COMPLETE,然后等待目标进程的BR_REPLY.
3.13 IPC::talkWithDriver
[->IPCThreadState.cpp]
1 | status_t IPCThreadState::talkWithDriver(bool doReceive) |
binder_write_read结构体用来与Binder驱动进行数据交换,通过ioctl与mDriverFD通信,主要操作的是mInt和mOut.
ioctl通过系统调用进入到Binder Driver。
四、Binder Driver
用户态的程序调用Kernel层驱动需陷入内核态,进行系统调用(syscall),其定义在kernel/include/linux/syscalls.h文件中
打开Binder驱动方法调用流程:ioctl->__ioctl->binder_ioctl,ioctl为用户空间的方法,
__ioctl是系统调用中相应的处理方法,通过查找找到内核binder驱动的binder_ioctl的方法。
上面传过来的是BINDER_WRITE_READ命令
4.1 binder_ioctl
[->android/binder.c]
1 | static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) |
binder_ioctl负责两个进程间收发IPC数据和IPC reply数据
binder_ioctl(文件描述符,ioctl命令,数据类型)
文件描述符,是通过binder_open方法打开Binder Driver后的返回值
ioctl命令和数据类型是一体的,不同的命令对应不同的数据类型
ioctl命令 | 数据类型 | 操作 |
---|---|---|
BINDER_WRITE_READ | struct binder_write_read | 收发Binder IPC数据 |
BINDER_SET_MAX_THREADS | __u32 | Binder线程最大个数 |
BINDER_SET_CONTEXT_MGR | __s32 | Service Manager节点 |
BINDER_THREAD_EXIT | __s32 | 释放Binder线程 |
BINDER_VERSION | struct binder_version | Binder版本信息 |
BINDER_GET_NODE_DEBUG_INFO | struct binder_node_debug_info | binder debug信息 |
4.1.1 binder_get_thread
[->android/binder.c]
1 | static struct binder_thread *binder_get_thread(struct binder_proc *proc) |
4.1.2 binder_get_thread_ilocked
[->android/binder.c]
1 | static struct binder_thread *binder_get_thread_ilocked( |
从binder_proc中查找binder_thread,如果当前线程已经加入到proc的线程队列则直接返回,如果不存在则创建binder_thread,并将当前线程添加到当期的proc。
4.2 binder_ioctl_write_read
[->android/binder.c]
1 | static int binder_ioctl_write_read(struct file *filp, |
4.3 binder_thread_write
[->android/binder.c]
1 | static int binder_thread_write(struct binder_proc *proc, |
4.4 binder_transaction
[->android/binder.c]
1 | static void binder_transaction(struct binder_proc *proc, |
binder_transaction主要的工作如下
注册服务的过程,传递的是BBinder对象,所以hdr->type为BINDER_TYPE_BINDER;
服务注册过程中是在服务所在的进程创建binder_node,在Servicemanager进程创建binder_ref,对应一个binder_node,每个进程只会创建一个binder_ref对象;
向当前线程的binder_proc->todo添加BINDER_WORK_TRANSACTION_COMPLETE事务,回复服务注册进程收到BC_TRANSACTION;
向servicemanager的binder_proc->todo添加BINDER_WORK_TRANSACTION事务,接下来进入到servicemanager进程中。
4.4.1 binder_translate_binder
[->android/binder.c]
1 | static int binder_translate_binder(struct flat_binder_object *fp, |
4.4.2 binder_proc_transaction
[->android/binder.c]
1 | static bool binder_proc_transaction(struct binder_transaction *t, |
4.2节中执行完binder_thread_write,再执行binder_thread_read操作,见4.5节
4.4.3 binder_inc_ref_for_node
[->android/binder.c]
1 | static int binder_inc_ref_for_node(struct binder_proc *proc, |
4.4.4 binder_get_ref_for_node_olocked
[->android/binder.c]
1 | static struct binder_ref *binder_get_ref_for_node_olocked( |
handle值计算方法规律:
- 每个进程binder_proc记录的binder_ref的handle值是从1开始递增的
- 所有进程的binder_proc所记录的handler=0的binder_ref都指向service manage
- 同一个服务的binder_node在不同进程的binder_ref的handle值可以不同
4.5 binder_thread_read
[->android/binder.c]
1 | static int binder_thread_read(struct binder_proc *proc, |
这里binder_thread_read主要是读取队列中的事务,将BR_TRANSACTION_COMPLETE命令写回客户端的用户空间,并且将BR_TRANSACTION命令写回服务端的用户空间。
下面看下服务端进程servicemanager。
五、ServiceManager进程
从第二大节中可以看到servicemanager启动后,循环再binder_loop过程,会调用binder_parse方法
5.1 binder_parse
[->servicemanager/binder.c]
1 | int binder_parse(struct binder_state *bs, struct binder_io *bio, |
5.2 svcmgr_handler
[->service_manager.c]
1 | int svcmgr_handler(struct binder_state *bs, |
5.3 do_add_service
[->service_manager.c]
1 | int do_add_service(struct binder_state *bs, const uint16_t *s, size_t len, uint32_t handle, |
5.4 binder_send_reply
[->servicemanager/binder.c]
1 | void binder_send_reply(struct binder_state *bs, |
将BC_FREE_BUFFER和BC_REPLY发送给binder驱动,向client发送reply。
5.5 binder_write
[->servicemanager/binder.c]
1 |
|
这里ioctl操作又回到驱动层,见第四节,流程和上面的一样,这里不再详细分析。
六、总结
6.1 servicemanager启动流程
1.打开Binder启动,调用mmap方法分配128K的内存映射空间:binder_open
2.通知binder驱动,使其成为上下文管理者,整个系统只有一个:binder_become_context_manager
3.进入循环等待,等待Client请求:binder_loop
6.2 addService核心过程
1 | public static void addService(String name, IBinder service) { |
通过创建JavaBBinder对象,将服务添加到ServiceManager中,和binder驱动的交互通过BpBinder.transact发送ADD_SERVICE_TRANSACTION实现添加,svclist保存所有已经注册的服务(包括服务名和handle信息)
6.3 通信流程
1.发起端进程向Binder Driver发送binder_ioct请求后,采用不断的循环talkWithDriver,此时线程处于阻塞状态,直到收到BR_TRANSACTION_COMPLETE命令才会结束该流程;
2.waitForResponse收到BR_TRANSACTION_COMPLETE命令后,则直接退出循环,不会再执行executeCommand方法,除六种其他命令外会执行该方法;
3.由于ServiceManager进程已经启动,并且有binder_loop一直在循环查询命令,当收到BR_TRANSACTION命令后,就开始处理addService过程。
附录
源码路径
1 | frameworks/base/core/java/android/os/ServiceManager.java |