Binder的一波分析

https://www.androidos.net.cn/sourcecode,这是一个非常好的网站,可以看Android的源码,各个版本的都有。最好下载下来,编译并且刷一次rom,有助于对整个android操作系统的理解。

 

 

由于Linux本身的进程间数据通信机制,管道的方式每次共享数据需要建立管道,更加耗费性能。减少管道建立可以通过共享内存的方式,但是Linux的共享内存的方式让共享空间空间管理困难,综上两种原因,所以Android自己设计了一套更加轻量级的Binder的机制。实现了只需要一次copy,需要的进程就可以共享。这儿是一整套机制,需要系统在开机时候就注册对应的服务,也就是具体的数据或者方法的提供者。C端通过Binder驱动连接上S端,从而在C端copy一次,服务端是可以直接访问那段空间,相对于共享内存,不需要copy_to_user。因此比共享内存要更加节省iO操作的性能。

 

如上,Binder的四个重要的角色,这儿在下面会从代码的角度来分析这个机制的,先了解一下大体的脉络。下面是Binder通信机制流程的两个流程图,都是非常好的。

 

 

Binder的优点如下:

Binder的架构设计如下:

 

binder只需要copy一次的原因,发送进程copy一次数据给内核空间的内核缓存区,内核缓存区与接收端进程之间有一个直接的映射关系,也就是Binder创建的接收缓存区,从而一次copy实现server端获取数据。

下面从源码的角度来分析一波binder:

对应的答案在这儿,可以对着源码进行分析,已经非常详细了:

1.打开binder设备(驱动)对应的代码:

frameworks->native->cmds->servicemanager->service_manager.c

main方法中有driver = "/dev/binder",意思是打开binder设备文件,返回文件描述符。

2.buffer的创建:

该文件的bs =binder_open(driver,128 *1024)这行代码,开辟一个128K的内存映射。

3.开辟内存映射:

上面的方法的调用位置,也就是内存映射的使用,也就对应了mmap命令的使用位置,因为只有mmap命令可已开辟内存(猜测),这个命令的使用位置,在frameworks->native->cmds->servicemanager->binder.c中。160行调用mmap.mmap里面的映射关系,是在系统启动的时候进行的。对应代码的位置是

device->google->cuttlefish_kernel->4.4-x86_64->System.map,在9.0的25306行就可以找到mmap的开启内存映射的代码。

4.ServiceManger启动:

对应代码位置system->core->rootdir->init.rc的413行,有start servicemanager,这儿就实现了配置和启动manger的操作。

5.打包parcel过程中,数据如何写入binder的:

对应代码位置frameworks->native->libs->binder->IServiceManager.cpp有一个addService()方法,这儿把传递过来的信息,打包成Parcel对象,并通过remote()->transact()方法往下一步进行传输。数据写入到binder设备,代码位置是frameworks->native->libs->binder->IPCThreadState.cpp第789行,调用

writeTransactionDate()方法,这是就是将Parcel对象中的信息封装成一个结构体writeTransactionDate,并且写入到 binder的过程当中,是在等待binder的返回结果的。

6.服务注册,添加到链表当中:

在frameworks->native->cmds->servicemanager->service_manager.c中,273进行了权限的检查,根据服务名在链表上,是否服务已经注册过,如果没有注册则分配内存并添加链表,同时进行过初始化为服务的操作。如果服务退出之后,需要通知serviceManager。

7.定义主线程中的线程池:

frameworks->native->libs->binder->include->binder->IPCThreadState.h这个头文件的75行,定义了joinThreadPool方法。具体的实现是在

frameworks->native->libs->binder->IPCThreadState.cpp中的第681行,有该方法joinThreadPool的具体实现,定义了一个主线程中的线程池,从而进行不停测读和写。在950行的方法IPCThreadState(),设置了一个读写的缓存区,大小为256K,主要工作就是从这里io操作,从而发送到binder里,具体是如何进入到binder的,是下一条的内容。

8.循环从mIn和mOut中取出读写请求,发送到binder中:

对应代码frameworks->native->libs->binder->IPCThreadState.cpp,在1110行,talkWithDriver()方法,前面是对读写的数据进行数据结构的补充,然后,里面的1168行,ioct1()方法,实现了发送到设备中。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值