`

Android Binder设计(四)

 
阅读更多
下表总结了当flat_binder_object结构穿过驱动时驱动所做的操作:
驱动对flat_binder_object的操作

Binder 类型( type 域)在发送方的操作在接收方的操作
BINDER_TYPE_BINDER

BINDER_TYPE_WEAK_BINDER
只有实体所在的进程能发送该类型的Binder。如果是第一次发送驱动将创建实体在内核中的节点,并保存binder,cookie,flag域。 如果是第一次接收该Binder则创建实体在内核中的引用;将handle域替换为新建的引用号;将type域替换为 BINDER_TYPE_(WEAK_)HANDLE
BINDER_TYPE_HANDLE

BINDER_TYPE_WEAK_HANDLE
获得Binder引用的进程都能发送该类型Binder。驱动根据handle域提供的引用号查找建立在内核的引用。如果找到说明引用号合法,否则 拒绝该发送请求。 如果收到的Binder实体位于接收进程中:将ptr域替换为保存在节点中的binder值;cookie替换为保存在节点中的cookie 值;type替换为BINDER_TYPE_(WEAK_)BINDER。

如果收到的Binder实体不在接收进程中:如果是第一次接收则创建实体在内核中的引用;将handle域替换为新建的引用号

BINDER_TYPE_FD 验证handle域中提供的打开文件号是否有效,无效则拒绝该发送请求。 在接收方创建新的打开文件号并将其与提供的打开文件描述结构绑定。

5.2.1 文件形式的 Binder
除了通常意义上用来通信的Binder,还有一种特殊的Binder:文件Binder。这种Binder的基本思想是:将文件看成Binder实 体,进程打开的文件号看成Binder的引用。一个进程可以将它打开文件的文件号传递给另一个进程,从而另一个进程也打开了同一个文件,就象Binder 的引用在进程之间传递一样。

一个进程打开一个文件,就获得与该文件绑定的打开文件号。从Binder的角度,linux在内核创建的打开文件描述结构struct file是Binder的实体,打开文件号是该进程对该实体的引用。既然是Binder那么就可以在进程之间传递,故也可以用 flat_binder_object结构将文件Binder通过数据包发送至其它进程,只是结构中type域的值为BINDER_TYPE_FD,表明 该Binder是文件Binder。而结构中的handle域则存放文件在发送方进程中的打开文件号。我们知道打开文件号是个局限于某个进程的值,一旦跨 进程就没有意义了。这一点和Binder实体用户指针或Binder引用号是一样的,若要跨进程同样需要驱动做转换。驱动在接收Binder的进程空间创 建一个新的打开文件号,将它与已有的打开文件描述结构struct file勾连上,从此该Binder实体又多了一个引用。新建的打开文件号覆盖flat_binder_object中原来的文件号交给接收进程。接收进 程利用它可以执行read(),write()等文件操作。

传个文件为啥要这么麻烦,直接将文件名用Binder传过去,接收方用open()打开不就行了吗?其实这还是有区别的。首先对同一个打开文件共享 的层次不同:使用文件Binder打开的文件共享linux VFS中的struct file,struct dentry,struct inode结构,这意味着一个进程使用read()/write()/seek()改变了文件指针另一个进程的文件指针也会改变;而如果两个进程分别使用 文件名打开同一文件则有各自的struct file结构,从而各自独立维护文件指针,互不干扰。其次是一些特殊设备文件要求在struct file一级共享才能使用,例如android的另一个驱动ashmem,它和Binder一样也是misc设备,用以实现进程间的共享内存。一个进程打 开的ashmem文件只有通过文件Binder发送到另一个进程才能实现内存共享,这大大提高了内存共享的安全性,道理和Binder增强了IPC的安全 性是一样的。

5.3 Binder 在驱动中的表述
驱动是Binder通信的核心,系统中所有的Binder实体以及每个实体在各个进程中的引用都登记在驱动中;驱动需要记录Binder引用 ->实体之间多对一的关系;为引用找到对应的实体;在某个进程中为实体创建或查找到对应的引用;记录Binder的归属地(位于哪个进程中);通过 管理Binder的强/弱引用创建/销毁Binder实体等等。

驱动里的Binder是什么时候创建的呢?前面提到过,为了实现实名Binder的注册,系统必须创建第一只鸡 – 为SMgr创建的,注册实名Binder专用的Binder实体,负责实名Binder注册过程中的进程间通信。既然创建了实体也要有对应的引用:驱动将 所有进程中的0号引用都预留给该Binder实体,即一开始所有进程的0号引用都指注册实名Binder专用的Binder,无须特殊操作任何进程通过0 号引用都可以注册实名Binder。接下来随着应用程序通过不断地注册实名Binder,不断向SMgr索要Binder的引用,不断将Binder从一 个进程传递给另一个进程,越来越多的Binder以传输结构 – flat_binder_object的形式穿越驱动做跨进程的迁徙。由于binder_transaction_data中data.offset数组 的存在,所有流经驱动的Binder都逃不过驱动的眼睛。Binder将对每个穿越进程边界的Binder做如下操作:检查传输结构的type域,如果是 BINDER_TYPE_BINDER或BINDER_TYPE_WEAK_BINDER则创建Binder的实体;如果是 BINDER_TYPE_HANDLE或BINDER_TYPE_WEAK_HANDLE则创建Binder的引用;如果是 BINDER_TYPE_HANDLE则为进程打开文件,无须创建任何数据结构。详细过程可参考表7。随着越来越多的Binder实体或引用穿过驱动在进 程间传递,驱动会在内核里创建越来越多的节点或引用,当然这个过程对用户来说是透明的。

5.3.1 Binder 实体在驱动中的表述
驱动中的Binder实体也叫‘节点’,隶属于提供实体的进程,由struct binder_node结构来表示:

Binder节点描述结构:binder_node
成员 含义
int debug_id; 用于调试
struct binder_work work; 当本节点引用计数发生改变,需要通知所属进程时,通过该成员挂入所属进程的to-do队列里,唤醒所属进程执行Binder实体引用计数的修改。
union { struct rb_node rb_node;struct hlist_node dead_node;}; 每个进程都维护一棵红黑树,以Binder实体在用户空间的指针,即本结构的ptr成员为索引存放该进程所有的Binder实体。这样驱动可以根据 Binder实体在用户空间的指针很快找到其位于内核的节点。rb_node用于将本节点链入该红黑树中。 销毁节点时须将rb_node从红黑树中摘除,但如果本节点还有引用没有切断,就用dead_node将节点隔离到另一个链表中,直到通知所有进程 切断与该节点的引用后,该节点才可能被销毁。
struct binder_proc *proc; 本成员指向节点所属的进程,即提供该节点的进程。
struct hlist_head refs; 本成员是队列头,所有指向本节点的引用都链接在该队列里。这些引用可能隶属于不同的进程。通过该队列可以遍历指向该节点的所有引用。
int internal_strong_refs; 用以实现强指针的计数器:产生一个指向本节点的强引用该计数就会加1。
int local_weak_refs; 驱动为传输中的Binder设置的弱引用计数。如果一个Binder打包在数据包中从一个进程发送到另一个进程,驱动会为该Binder增加引用计 数,直到接收进程通过BC_FREE_BUFFER通知驱动释放该数据包的数据区为止。
int local_strong_refs; 驱动为传输中的Binder设置的强引用计数。同上。
void __user *ptr; 指向用户空间Binder实体的指针,来自于flat_binder_object的binder成员
void __user *cookie; 指向用户空间的附加指针,来自于flat_binder_object的cookie成员
unsigned has_strong_ref; unsigned pending_strong_ref;unsigned has_weak_ref;unsigned pending_weak_ref 这一组标志用于控制驱动与Binder实体所在进程交互式修改引用计数
unsigned has_async_transaction; 该成员表明该节点在to-do队列中有异步交互尚未完成。驱动将所有发送往接收端的数据包暂存在接收进程或线程开辟的to-do队列里。对于异步交 互,驱动做了适当流控:如果to-do队列里有异步交互尚待处理则该成员置1,这将导致新到的异步交互存放在本结构成员 – asynch_todo队列中,而不直接送到to-do队列里。目的是为同步交互让路,避免长时间阻塞发送端。
unsigned accept_fds 表明节点是否同意接受文件方式的Binder,来自flat_binder_object中flags成员的 FLAT_BINDER_FLAG_ACCEPTS_FDS位。由于接收文件Binder会为进程自动打开一个文件,占用有限的文件描述符,节点可以设置 该位拒绝这种行为。
int min_priority 设置处理Binder请求的线程的最低优先级。发送线程将数据提交给接收线程处理时,驱动会将发送线程的优先级也赋予接收线程,使得数据即使跨了进 程也能以同样优先级得到处理。不过如果发送线程优先级过低,接收线程将以预设的最小值运行。 该域的值来自于flat_binder_object中flags成员。
struct list_head async_todo 异步交互等待队列;用于分流发往本节点的异步交互包

分享到:
评论

相关推荐

    Android Binder设计与实现——设计篇

    罗升阳在介绍和学习Binder的Blog中推荐:《Android Binder设计与实现》一文,详细地介绍了内核空间的Binder驱动程序的数据结构和设计原理

    Android Binder设计与实现

    详细分析了android binder的设计与实现。

    Android_Binder设计与实现_-_设计篇

    Android_Binder设计与实现_-_设计篇

    Android Binder设计与实现.docx

    Android Binder设计与实现.docxAndroid Binder设计与实现.docxAndroid Binder设计与实现.docxAndroid Binder设计与实现.docxAndroid Binder设计与实现.docxAndroid Binder设计与实现.docxAndroid Binder设计与实现....

    Android Binder设计之道.pptx

    Android Binder设计之道.pptx

    AndroidBinder设计与实现-设计篇

    Binder是Android系统进程间通信(IPC)方式之一。Linux已经拥有管道,systemVIPC,socket等IPC手段,却还要倚赖Binder来实现进程间通信,说明Binder具有无可比拟的优势。深入了解Binder并将之与传统IPC做对比有助于...

    android中binder设计与实现

    android中binder设计与实现 与深入浅出结合,非常好的诠释了android 中的binder机制的实现,各有所长,希望对您有帮助 个人也是网络上找的

    Android Binder 实现原理

    很详细讲解了Binder实现原理,细节,设计思想

    Binder设计与实现

    Binder是Android系统进程间通信(IPC)方式之一。Linux已经拥有管道,system V IPC,socket等IPC手段,却还要倚赖Binder来实现进程间通信,说明Binder具有无可比拟的优势。深入了解Binder并将之与传统 IPC做对比有助...

    Android Binder通信案例

    AIDL实现IPC,手写Binder实现IPC,Binder连接池的设计

    Android10.0 Binder通信原理(九)-AIDL Binder示例

    摘要:本节主要来讲解Android10.0 Binder中如何使用AIDL 阅读本文大约需要花费20分钟。 文章首发微信公众号:IngresGe 专注于Android系统级源码分析,Android的平台设计,欢迎关注我,谢谢! [Android取经之路] 的...

    Android Binder

    本文将对Binder的设计细节做一个全面的阐述,首先通过介绍Binder通信 模型和 Binder通信协议了解Binder的设计需求;然后分别阐述Binder在系统不同部分的表述方式和起的作用;最后还 会解释Binder在数据接收端的设计...

    Android代码-Android

    对于Binder机制的介绍可以看universus写的《Android Binder设计与实现》。另外还两个老外介绍Binder的PPT也不错。 Android Binder设计与实现 - 设计篇 inter-process method invocation in Android (相对入门一点...

    Android的设计与实现(卷1)

    “android的设计与实现”系列丛书主要围绕android系统的四层结构展开,通过源代码来分析各层的设计思想与实现原理,卷i则主要是针对framework(框架层)的。全书共12章,分为六个部分:基础篇(第1~2章)详细讲解了...

    android native层 binder通信机制演示源码

    该压缩包的内容主要是基于android系统演示native层进行binder通信的源码,里面分为bp和bn直接如何设计,可以给那些需要再native层进行binder通信的开发提供一个参考

    Android Binder入门学习笔记

    理解Binder能帮助我们更好的理解Android的系统设计,比如说四大组件,AMS,WMS等系统服务的底层通信机制就都是基于Binder机制的。当然了,Binder机制的底层驱动实现很复杂,本文的目的只是为了理清Binder的使用和在...

    基于Android的家庭理财系统的设计与实现.rar(毕业论文设计+程序源码) android studio导入可直接打开

    2.4.4 Binder 机制 15 2.5本章小结 16 第3章 需求分析与数据库设计 16 3.1需求分析 16 3.1.1功能性需求分析 16 3.12非功能性需求分析 17 3.2系统数据库设计 17 3.2.1数据库概念结构设计 17 3.2.2数据库逻辑结构设计 ...

    Android的设计与实现 卷1 (带目录)

    “Android的设计与实现”系列丛书主要围绕Android系统的四层结构展开,通过源代码来分析各层的设计思想与实现原理,卷I则主要是针对Framework(框架层)的。 全书共12章,分为六个部分: 基础篇(第1~2章)详细讲解...

Global site tag (gtag.js) - Google Analytics