2.1 Binder在传输数据中的表述flat_binder_object
Binder可以在数据包的有效数据中越过进程边界从一个进程传递给另一个进程,这些传输中的Binder用 flat_binder_object结构来表示,如上所示
无论是Binder实体还是对实体的引用都从属于某个进程,所以该结构不能透明地在进程之间传输,必须有驱动的参与。例如当Server把 Binder实体传递给Client时,在发送数据中,flat_binder_object中的type是 BINDER_TYPE_BINDER,binder指向Server进程用户空间地址。如果透传给接收端将毫无用处,驱动必须对数据流中的这个 Binder做修改:将type该成BINDER_TYPE_HANDLE;为这个Binder在接收进程中创建位于内核中的引用并将引用号填入 handle中。对于发生数据流中引用类型的Binder也要做同样转换。经过处理后接收进程从数据流中取得的Binder引用才是有效的,才可以将其填 入数据包binder_transaction_data的target.handle域,向Binder实体发送请求。
这样做也是出于安全性考虑:应用程序不能随便猜测一个引用号填入target.handle中就可以向Server请求服务了,因为驱动并没有为你 在内核中创建该引用,必定会驱动被拒绝。唯有经过身份认证确认合法后,由‘权威机构’通过数据流授予你的Binder才能使用,因为这时驱动已经在内核中 为你建立了引用,交给你的引用号是合法的。
2.2 Binder对象的类型
2.5 Binder实体在驱动中的表述 binder_node
驱动中的Binder实体也叫‘节点’,隶属于提供实体的进程,由struct binder_node结构来表示
每个进程都有一棵红黑树用于存放创建好的节点,以Binder在用户空间的指针作为索引。每当在传输数据中侦测到一个代表Binder实体的 flat_binder_object,先以该结构的binder指针为索引搜索红黑树;如果没找到就创建一个新节点添加到树中。由于对于同一个进程来说 内存地址是唯一的,所以不会重复建设造成混乱。
2.6 Binder引用在驱动中的表述--引用描述结构:binder_ref
和实体一样,Binder的引用也是驱动根据传输数据中的flat_binder_object创建的,隶属于获得该引用的进程,用struct binder_ref结构体表示
就象一个对象有很多指针一样,同一个Binder实体可能有很多引用,不同的是这些引用可能分布在不同的进程中。和实体一样,每个进程使用红黑树存放所有该进程正在使用的引用。但Binder的引用可以通过两个键值索引:
2.7 Binder节点、进程、线程结构
binder_transaction:
binder_node:
binder_work:
binder_proc:
binder_thread:
3.1 binder_init
binder_init()初始化函数流程:
3.2 binder_ioctl
在该函数中,一共有7个命令,但只实现了5个。在用户空间通过ioctl函数调用相应底层驱动的命令,来实现相应的方法。
3.2.1 BINDER_WRITE_READ
这个io操作码有一个参数,形式为struct binder_write_read
BINDER_WRITE_READ命令流程:
Binder收发数据包结构:binder_transaction_data
和写数据一样,其中最重要的消息是BR_TRANSACTION 或BR_REPLY,表明收到了一个格式为binder_transaction_data的请求数据包(BR_TRANSACTION)或返回数据包 (BR_REPLY)
Binder写操作命令字(code)
在这些命令中,最常用的是BC_TRANSACTION/BC_REPLY命令对,Binder数据通过这对命令发送给接收方。这对命令所承载的数 据包由结构体struct binder_transaction_data定义。Binder交互有同步和异步之分,利用binder_transaction_data中 flag域区分。如果flag域的TF_ONE_WAY位为1则为异步交互,即Client端发送完请求交互即结束, Server端不再返回BC_REPLY数据包;否则Server会返回BC_REPLY数据包,Client端必须等待接收完该数据包方才完成一次交 互。
Binder读操作命令字(code)
和写数据一样,其中最重要的消息是BR_TRANSACTION 或BR_REPLY,表明收到了一个格式为binder_transaction_data的请求数据包(BR_TRANSACTION)或返回数据包 (BR_REPLY)
3.2.2 BINDER_SET_CONTEXT_MGR命令
作用是:将当前进程注册为SMgr。系统中同时只能存在一个SMgr。只要当前的SMgr没有调用close()关闭Binder驱动就不能有别的进程可以 成为SMgr。
流程:
这个命令是将一个进程/线程设置为Context Manager。该命令一般在系统启动时初始化Binder驱动的过程中被调用
3.2.3 BINDER_SET_MAX_THREADS
该命令告知Binder驱动接收方(通常是Server端)线程池中最大的线程数。由于Client是并发向Server端发送请求 的,Server端必须开辟线程池为这些并发请求提供服务。告知驱动线程池的最大值是为了让驱动在线程达到该值时不要再命令接收端启动新的线程。
3.2.4 BINDER_THREAD_EXIT
通知Binder驱动当前线程退出了。Binder会为所有参与Binder通信的线程(包括Server线程池中的线程和Client发出请求的 线程)建立相应的数据结构。这些线程在退出时必须通知驱动释放相应的数据结构。
3.2.5 BINDER_VERSION
获得Binder驱动的版本号
3.3 binder_open
流程:
3.4 binder_release
流程:
3.5 binder_flush
流程:
此函数一般在将在关闭一个设备文件描述符复制时被调用
3.6 binder_poll
实现非阻塞IO模型函数流程:
3.7 binder_mmap
注意:mmap函数的第二个参数为VMA的结构体指针,VMA是用来管理进程地址空间中不同区域的数据结构,由内核来维持。最终的作用是把分配的空间加入到VMA区域中去。VMA在mmap函数中会被使用。
内存空间映射函数流程: