https://blog.csdn.net/tkwxty/article/details/102904305 (非常详细!)
目录
一、架构
源码位置:frameworks/native/cmds/servicemanager/service_manager.c
- 与zygote关系:与zygote通讯,servicemanager重启会导致zygote也重启,见其rc文件。
- 与system_server关系:
ServiceManager 用来管理各种 Service,使用 C/S 架构,Binder 通信机制。Client 端要使用某个 Service,先要到 ServiceManager 查询 Service 的相关信息,然后根据 Service 的相关信息与 Server 端建立通信通路。
二、源码分析
main函数
1.binder_open函数
函数实现于frameworks/native/cmds/servicemanager/binder.c
97 struct binder_state *binder_open(const char* driver, size_t mapsize)
98 {
...
108 bs->fd = open(driver, O_RDWR | O_CLOEXEC);
...
124 bs->mapped = mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, bs->fd, 0);
138 }
open与mmap方法最终会调用到binder驱动kernel/msm-4.19/drivers/android/binder.c
主要有两个操作:
1)ServiceManager进程:就是打开/dev/binder,同时映射物理内存到进程空间。
2)Binder驱动:新建并初始化该进程对应的binder_proc结构体,同时将内核虚拟地址和该进程的虚拟地址映射到同一物理内存中。(Binder进程间通信机制的精髓所在!!)
在Binder通信机制中,mmap()会将Server进程的虚拟地址和内核虚拟地址映射到同一个物理页面。那么当Client进程向Server进程发送请求时,只需要将Client的数据拷贝到内核空间即可!由于Server进程的地址和内核空间映射到同一个物理页面,因此,Client中的数据拷贝到内核空间时,也就相当于拷贝到了Server进程中。因此,Binder通信机制中,数据传输时,只需要1次内存拷贝!
2.binder_become_context_manager函数
1)在用户层通知Kernel Binder驱动,当前进程(即ServiceManager进程)是Binder上下文管理者,当然Binder驱动也不是那么好糊弄的会经过一些系列的安全检验,必须先验证身份。这样ServiceManager就成为了经常被各个binder博客中提到的服务大管家。
2)在内核Binder驱动层,新建当前线程对应的binder_thread对象,并将其添加到进程上下文信息binder_proc的threads红黑树中;新建ServiceManager对应的binder实体,并将该binder实体保存到全局变量binder_context_mgr_node中。
对于每一个Binder service,Binder驱动都会为其分配一个binder_node对象。对于ServiceManager这个Binder上下文管理者而言,Binder驱动更是会将它的Binder实体保存到全局变量binder_context_mgr_node 中。
3.binder_loop函数
首先调用binder_write(,BC_ENTER_LOOPER,)告诉Kernel Binder驱动,我(ServiceManager进程)准备要进入消息循环状态了,请做好相关的准备。紧接着,就通过ioctl(,BINDER_WRITE_READ,)进入消息循环,等待Client发送请求(例如,MediaPlayer进程调用addService将MediaPlayer注册到ServiceManager中进行管理)。如果没有消息,则进入中断等待状态;如果有消息,则进行消息处理!
三、defaultServiceManager()
其它进程可以通过此方法获取到ServiceManager服务的代理对象,具体分析见:https://blog.csdn.net/tkwxty/article/details/103034523
最终返回的是BpServiceManager对象
gDefaultServiceManager = new BpServiceManager(new BpBinder(0));
0 条评论