在看Binder源码时,总是接触到很多这些莫名其妙的struct,故依据几本参考资料先把这些数据结构的意义即关系整理以下:
/** \kernel\goldfish\drivers\staging\android\binder.c*/
//表示binder驱动中进程所要处理的工作项 struct binder_work { struct list_head entry; //用于实现一个双向链表,存储所有binder_work的队列 enum { BINDER_WORK_TRANSACTION = 1, BINDER_WORK_TRANSACTION_COMPLETE, BINDER_WORK_NODE, BINDER_WORK_DEAD_BINDER, BINDER_WORK_DEAD_BINDER_AND_CLEAR, BINDER_WORK_CLEAR_DEATH_NOTIFICATION, } type; //描述工作项的类型 };
//存储Binder线程池中的每个线程的信息 struct binder_thread { struct binder_proc *proc; //宿主进程,即线程属于哪个Binder进程 struct rb_node rb_node; //红黑树中的一个节点,binder_proc使用红黑树来组织Binder线程池中的线程 int pid; //当期线程PID int looper; //当前线程状态信息 struct binder_transaction *transaction_stack;//事务堆栈,将事务封装成binder_transaction,添加到事务堆栈中,定义了要接收和发送的进程和线程消息 struct list_head todo; //队列,当有来自Client的请求时,将会添加到to_do队列中 uint32_t return_error; //记录处理事务时出现异常错误情况信息 uint32_t return_error2; wait_queue_head_t wait; /* 等待队列,当Binder处理T1事务依赖于其他Binder线程处理事务T2时, 则会sleep在wait所描述的等待队列中,直至T2事务处理完成再唤醒*/ struct binder_stats stats; //Binder线程相关统计数据 }; //looper状态值 enum { BINDER_LOOPER_STATE_REGISTERED = 0x01, //Binder驱动请求创建该线程,通过BC_REGISTER_LOOPER协议通知Binder驱动,注册成功设为此状态 BINDER_LOOPER_STATE_ENTERED = 0x02, //该线程是应用程序主动注册的, BC_ENTER_LOOPER BINDER_LOOPER_STATE_EXITED = 0x04, //Binder线程退出, BC_EXIT_LOOPER BINDER_LOOPER_STATE_INVALID = 0x08, //异常情况 BINDER_LOOPER_STATE_WAITING = 0x10, //Binder线程处于空闲状态 BINDER_LOOPER_STATE_NEED_RETURN = 0x20 /*表示该线程需要马上返回到用户空间中,使用情形 : 一:线程注册成为Binder线程后,还没准备好去处理进程间通信,需要返回用户空间做其他初始化等准备 二:进程调用flush来刷新Binder线程池*/ };
//Binder线程相关统计计数 struct binder_stats { int br[_IOC_NR(BR_FAILED_REPLY) + 1]; // 用于存储BINDER_WRITE_READ读操作命令协议 int bc[_IOC_NR(BC_DEAD_BINDER_DONE) + 1]; // 用于存储BINDER_WRITE_READ写操作命令协议 int obj_created[BINDER_STAT_COUNT]; // 保存对象计数 int obj_deleted[BINDER_STAT_COUNT]; };
/** 描述一个正在使用Binder进程通信的进程,binder_proc为管理其信息的记录体 * 当一个进程open /dev/binder时,Binder驱动程序会为其创建一个binder_proc结构体,用以记录该进程的所有相关信息 * 并把该结构体保存到一个全局的hash表中*/ struct binder_proc { /** 进程相关参数*/ struct hlist_node proc_node; // 上述全局hash表中的一个节点,用以标记该进程 int pid; // 进程组ID struct task_struct *tsk; // 任务控制模块 struct files_struct *files; // 文件结构体数组 /** Binder线程池——每一个Binder进程都有一个线程池,由Binder驱动程序来维护 * Binder线程池中所有线程由一个红黑树来组织,RB树以线程ID为关键字;*/ struct rb_root threads; // 上述红黑树根节点 /* 进程可以调用ioctl注册线程到Binder驱动程序中;当线程池中没有足够空闲线程来处理事务时, * Binder驱动程序可以主动要求进程注册更多的线程到Binder线程池中*/ int max_threads; // Binder驱动程序最多可以请求进程注册的线程的数量 int requested_threads; // Binder驱动程序每主动请求进程添加注册一个线程时,requested_threads加1 int requested_threads_started; // 进程响应Binder要求后,requested_threads_started + 1;requested_threads - 1 // 表示Binder已经主动请求注册的线程数目 int ready_threads; // 进程当前空闲Binder线程数目 long default_priority; // 线程优先级,初始化为进程优先级 /** 一系列Binder实体对象(binder_node)和Binder引用对象(binder_ref) 老罗对此做的概念区分: 1. 在用户空间,运行在Server端的称为Binder本地对象,运行在Client端的称为Binder代理对象。 2. 在内核空间,Binder实体对象用来描述Binder本地对象,Binder引用对象用来描述Binder代理对象。*/ struct rb_root nodes; // Binder实体对象列表(RB树),关键字ptr struct rb_root refs_by_desc; // Binder引用对象,关键字desc struct rb_root refs_by_node; // Binder引用对象,关键字node /** mmap内核缓冲区*/ struct vm_area_struct *vma; // mmap——分配的内核缓冲区 用户空间地址(相较于buffer) void *buffer; // mmap——分配的内核缓冲区 内核空间地址(相较于vma)(两者都是虚拟地址) ptrdiff_t user_buffer_offset; // mmap——buffer与vma之间的差值 /** buffer指向的内核缓冲区,被划分成很多小块进行管理;这些小块保存在列表中,buffers就是列表头部*/ struct list_head buffers; // 内核缓冲区列表 struct rb_root free_buffers; // 空闲的内存缓冲区(红黑树) struct rb_root allocated_buffers; // 正在使用的内存缓冲区(红黑树) size_t free_async_space; // 当前可用来保存异步事务数据的内核缓冲区大小 struct page **pages; // 对应于vma、buffer虚拟地址,这里是它们对应的物理页面 size_t buffer_size; // 内核缓冲区大小 uint32_t buffer_free; // 空闲内核缓冲区大小 /** 进程每接收到一个通信请求,Binder将其封装成一个工作项,保存在待处理队列to_do中*/ struct list_head todo; // 待处理工作队列 wait_queue_head_t wait; // 等待队列,存放一些睡眠的空闲Binder线程 struct hlist_node deferred_work_node;// hash表,保存进程中可以延迟执行的工作项 int deferred_work; // 延迟工作项的具体类型 struct binder_stats stats; // 统计进程相关数据,具体参见binder_stats结构 struct list_head delivered_death; // 表示Binder驱动程序正在向进程发送的死亡通知 };
5、binder_node:
/** 描述一个Binder实体对象,每一个Service组件在Binder驱动程序中都对应一个Binder实体对象 * Binder驱动程序通过强引用和弱引用计数来维护其生命周期*/ struct binder_node { int debug_id; // 用以调试 struct binder_work work; // /** 每一个binder进程都由一个binder_proc来描述 * binder进程内部所有Binder实体对象,由一个红黑树进行组织(struct rb_root nodes) * rb_node则对应nodes其中的一个节点*/ union { struct rb_node rb_node; // 用于将本节点连接点红黑树中 struct hlist_node dead_node; /* 如果Binder实体对象对应的进程死亡,销毁节点时需要将rb_node从红黑树中删除, 如果本节点还有引用没有切断,则用dead_node 将其隔离到另一个链表中, 直到通知所有进程切断与该节点的引用后,该节点才能销毁*/ }; /* binder_proc 和 binder_node 关系: * 可以将binder_proc理解为一个进程,而将binder_node理解为一个Service。 * binder_proc里面有一个红黑树,用来保存所有在它所描述的进程里面创建的Service, * 而每一个Service在Binder驱动程序里面都用一个binder_node来描述。 * */ struct binder_proc *proc; // 指向该Binder实体对象对应的进程,进程由binder_proc描述 struct hlist_head refs; /* 该Bidner实体对象可能同时被多个Client组件引用,所有指向本实体对象的引用都保存到这个hash队列中 refs表示队列头部;这些引用可能隶属不同进程,遍历该hash表能够得到哪些Client组件引用了该对象*/ /** 引用计数 * 1、当一个Bidner实体对象请求一个Service组件来执行Bidner操作时。会增加该Service组件的强/弱引用计数 * 同时,Binder实体对象会将has_strong_ref与has_weak_ref置为1 * 2、当一个Service组件完成一个Binder实体对象请求的操作后,Binder对象会请求减少该Service组件的强/弱引用计数 * 3、Binder实体对象在请求一个Service组件增加或减少强/弱引用计数的过程中,会将pending_strong_ref和pending_weak_ref置为1 * 当Service组件完成增加或减少计数时,Binder实体对象会将这两个变量置为0*/ int internal_strong_refs; // 强引用计数 int local_weak_refs; // 弱引用计数 int local_strong_refs; // 强引用计数 unsigned has_strong_ref : 1; unsigned pending_strong_ref : 1; unsigned has_weak_ref : 1; unsigned pending_weak_ref : 1; /** 用来描述用户空间中的一个Service组件*/ void __user *ptr; // 指向该Service组件内部的一个引用计数对象(weakref_impl)的地址?? void __user *cookie; // 指向该Service组件的地址 /** 异步事务处理,目的在于为同步交互让路,避免长时间阻塞发送端 * 异步事务的定义:(相对于同步事务)单向的进程间通信要求,即不需要等待应答的进程间通信请求 * Binder驱动程序认为异步事务的优先级低于同步事务,则在同一时刻,一个Binder实体对象至多只有一个异步事务会得到处理;而同步事务则无此限制 * * Binder将事务保存在一个线程binder_thread的todo队列中,表示由该线程来处理该事务 * 每一个事务都关联Binder实体对象(union target),表示该事务的目标处理对象,表示要求该Binder实体对象对应的Serice组件在指定线程中处理该事务 * 而如果Binder发现一个事务是异步事务,则会将其保存在目标Binder实体对象的async_todo的异步事务队列中等待处理*/ unsigned has_async_transaction : 1;// 描述该Binder实体对象是否正在处理一个异步事务,1 表示是 struct list_head async_todo; /* 表示该Binder实体对象能否接收包含有该文件描述符的进程间通信数据。 * 当一个进程向另一个进程发送数据中包含文件描述符时,Binder会在目标进程中打开一个相同的文件 * 故设为accept_fds为0可以防止源进程在目标进程中打开文件*/ unsigned accept_fds : 1; int min_priority : 8; // 处理Binder请求的线程的最低优先级 };
/** 用来描述一个Binder引用对象,每一个Client组件在Binder驱动程序中都有一个Binder引用对象,用来描述它在内核中的状态*/ struct binder_ref { /* Lookups needed: */ /* node + proc => ref (transaction) */ /* desc + proc => ref (transaction, inc/dec ref) */ /* node => refs + procs (proc exit) */ int debug_id; // 用以调试 /** binder_proc中使用红黑树(对应两个rb_root变量)来存储其内部所有的引用对象 * 下面rb_node则是红黑树中的节点*/ struct binder_proc *proc; // Binder引用对象的宿主进程 struct rb_node rb_node_desc; // 对应refs_by_desc,以句柄desc索引 struct rb_node rb_node_node; // 对应refs_by_node,以node索引 /** Client通过Binder访问Service时,仅需指定一个句柄值,Binder通过该desc找到对应binder_ref,再根据该 * binder_ref中的node变量得到binder_node(实体对象),进而找到对应的Service组件*/ struct hlist_nod enode_entry; // 对应Binder实体对象中(hlist_head)refs引用对象队列中的一个节点 struct binder_node *node; // 引用对象所指向的Binder实体对象 uint32_t desc; // 句柄,用以描述该Binder引用对象 // 强弱引用计数 int strong; int weak; /* 表示Service组件接收到死亡通知;*/ struct binder_ref_death *death; };7、binder_ref_death :
// 一个死亡通知结构体 /** 易知Client组件无法控制他所引用的Service组件的生命周期,由于Service组件所在进程可能意外崩溃 * Client进程就需要能够在它所引用的Service组件死亡时获得通知,进而进行响应。 * 则Client进程就需要向Binder驱动程注册一个用来接收死亡通知的对象地址(这里的cookie)*/ struct binder_ref_death { struct binder_work work;// 标志该通知具体的死亡类型 void __user *cookie; // 保存负责接收死亡通知的对象地址 }; /** Binder驱动向Client进程发送死亡通知的情形如下: * 1、Binder驱动监测到Service组件死亡时,会找到对应Service实体对象(binder_node),再通过refs变量找到引用它的所有Client进程(binder_ref) * 再通过death变量找到Client进程向Binder注册的死亡通知接收地址; * Binder将该死亡通知binder_ref_death封装成工作项,添加到Client进程的to_do队列中等待处理。 * 这种情况binder_work类型为BINDER_WORK_DEAD_BINDER * 2、Client进程向Binder驱动程序注册一个死亡接收通知时 * 如果它所引用的Service组件已经死亡,Binder会立即发送通知给Client进程; * 这种情况binder_work类型为BINDER_WORK_DEAD_BINDER * * 3、当Client进程向Binder驱动程序注销一个死亡通知时,也会发送通知,来响应注销结果 * 1)当Client注销时,Service组件还未死亡:Binder会找到之前Client注册的binder_ref_death, * 将binder_work修改为BINDER_CLEAR_DEATH_NOTIFICATION,并将通知按上述步骤添加到Client的to_do对列中 * 2)当Client注销时,Service组件已经死亡,Binder同理将binder_work修改为WORK_DEAD_BINDER_AND_CLEAR,然后添加到todo中 * */8、binder_state :
struct binder_state { int fd; //打开/dev/binder之后得到的文件描述符 void *mapped; //mmap将设备文件映射到本进程的地址空间中,映射后得到的地址空间地址、及大小 size_t mapsize; };9、binder_buffer :
/** 内核缓冲区,用以在进程间传递数据 * 回顾binder_proc中的vma与buffers(内核缓冲区列表)*/ struct binder_buffer { // entry对应内核缓冲区列表buffers中的一个节点 struct list_head entry; /* free and allocated entries by addesss */ /** 结合free,如果free=1,则rb_node对应free_buffers中一个节点(空闲内核缓冲区) * 如果free!=1,则对应allocated_buffers中一个节点*/ struct rb_node rb_node; /* free entry by size or allocated entry */ unsigned free : 1; /** Binder将事务数据保存到一个内核缓冲区中(binder_transaction.buffer),然后交由Binder实体对象(target_node)处理 * 而target_node会将缓冲区的内容交给对应的Service组件(proc)来处理 * Service组件处理完事务后,若allow_user_free=1,则请求Binder释放该内核缓冲区*/ unsigned allow_user_free : 1; struct binder_transaction *transaction;// 描述一个内核缓冲区正在交给哪个事务transaction,用以中转请求和返回结果 struct binder_node *target_node; // 描述该缓冲区正在被哪个Binder实体对象使用 unsigned async_transaction : 1; // 1表示事务是异步的;异步事务的内核缓冲区大小是受限的,这样可以保证同步事务可以优先得到缓冲区 unsigned debug_id : 29; // 用以调试 /** 存储通信数据,通信数据中有两种类型数据:普通数据与Binder对象, * 在数据缓冲区最后,有一个偏移数组,记录数据缓冲区中每一个Binder对象在缓冲区中的偏移地址*/ size_t data_size; // 数据缓冲区大小 size_t offsets_size; // 偏移数组的大小(其实也是偏移位置) uint8_t data[0]; // 用以保存通信数据,数据缓存区,大小可变 };10、binder_transaction :
//描述进程间通信,这个过程称为一个transaction(事务),用以中转请求和返回结果,并保存接收和要发送的进程信息 struct binder_transaction { int debug_id; struct binder_work work; // 用来描述待处理的工作项,这里会将其type设置为BINDER_WORK_TRANSACTION,具体结构见binder_work /** 源线程*/ struct binder_thread *from; // 源线程,即发起事务的线程 long priority; // 源线程的优先级 uid_t sender_euid; // 源线程的用户ID /** 目标线程*/ struct binder_proc *to_proc; // 目标进程,处理该事务的进程(process) struct binder_thread *to_thread; // 目标线程:处理该事务的线程 /** 《源代码分析》中的例子:线程A发起事务T1,需要由B线程处理;B处理T1时,需要C先处理T2;C处理T2时,又需要A处理T1; * 则T1依赖于T2,T2依赖于T3; A 要处理T1,T3,但要先处理T3 * 故: T2->from_parent = T1 * T3->from_parent = T2 * T3->to_parent = T1*/ struct binder_transaction *from_parent; // 表示另一个事务需要依赖该事务(不一定在同一线程中) struct binder_transaction *to_parent; // 目标线程下一个需要处理的事务 unsigned need_reply : 1; // 标志事务是同步/异步;设为1——表示同步事务,需要等待对方回复;设为0——异步 /*unsigned is_dead : 1;*//* not used at the moment */ /** 参照binder_buffer中解释,指向Binder为该事务分配的内核缓冲区 * code与flags参见binder_transaction_data */ struct binder_buffer *buffer; unsigned int code; unsigned int flags; /** 目标线程处理事务前,Binder需要修改其priority;修改前需要将线程原来的priority保存到saved_priority中,用以处理完事务恢复到原来优先级 * 优先级的设置:目标线程处理事务时,优先级应不低于目标Service组件要求的线程优先级,也不低于源线程的优先级;故设为两者的较大值*/ long saved_priority; };11、 binder_transaction_data:
/* 描述进程间通信所传输的数据: * Binder对象的传递是通过binder_transaction_data来实现的, * 即Binder对象实际是封装在binder_transaction_data结构体中。*/ struct binder_transaction_data { /** 有一个联合体target,当这个BINDER_WRITE_READ命令的目标对象是本地Binder实体时, 就使用ptr来表示这个对象在本进程中的地址,否则就使用handle来表示这个Binder实体的引用。 只有目标对象是Binder实体时,cookie成员变量才有意义,表示一些附加数据; 详细的解释为:传输的数据是一个复用数据联合体,对于BINDER类型,数据就是一个binder本地对象, 如果是HANDLE类型,这数据就是一个远程的handle对象。该如何理解本地binder对象和远程handle对象呢? 其实它们都指向同一个对象,不过是从不同的角度来说。举例来说,假如A有个对象X,对于A来说, X就是一个本地的binder对象;如果B想访问A的X对象,这对于B来说,X就是一个handle。 因此,从根本上来说handle和binder都指向X。本地对象还可以带有额外的数据,保存在cookie中。 */ union { size_t handle;/* target descriptor of command transaction */ void *ptr; /* target descriptor of return transaction */ } target; //Binder实体带有的附加数据 void *cookie; /* target object cookie */ //code是一个命令,描述了请求Binder对象执行的操作,表示要对目标对象请求的命令代码 unsigned int code; /* transaction command */ /* transaction的基本信息*/ //事务标志,见transaction_flags unsigned int flags; pid_t sender_pid; // 发起请求的进程PID uid_t sender_euid; // 发起请求的进程UID size_t data_size; //data.buffer缓冲区的大小,data见最下面定义;命令的真正要传输的数据就保存在data.buffer缓冲区中 size_t offsets_size; //data.offsets缓冲区的大小 union { struct { /* transaction data */ const void *buffer; /* offsets from buffer to flat_binder_object structs */ const void *offsets; } ptr; uint8_t buf[8]; } data; /** 命令的真正要传输的数据就保存在data.buffer缓冲区中,前面的一成员变量都是一些用来描述数据的特征的。 data.buffer所表示的缓冲区数据分为两类,一类是普通数据,Binder驱动程序不关心, 一类是Binder实体或者Binder引用,这需要Binder驱动程序介入处理。为什么呢? 想想,如果一个进程A传递了一个Binder实体或Binder引用给进程B,那么, Binder驱动程序就需要介入维护这个Binder实体或者引用的引用计数,防止B进程还在使用这个Binder实体时, A却销毁这个实体,这样的话,B进程就会crash了。所以在传输数据时,如果数据中含有Binder实体和Binder引和, 就需要告诉Binder驱动程序它们的具体位置,以便Binder驱动程序能够去维护它们。 data.offsets的作用就在这里了,它指定在data.buffer缓冲区中,所有Binder实体或者引用的偏移位置。 注:: 进程间传输的数据被称为Binder对象(Binder Object), 它是一个flat_binder_object。Binder对象的传递是通过binder_transaction_data来实现的, 即Binder对象实际是封装在binder_transaction_data结构体中。*/ };12、 transaction_flags:
/* transaction_flags描述了传输方式,比如同步、异步等*/ enum transaction_flags { TF_ONE_WAY = 0x01, /* 当前事务异步,不需要等待*/ TF_ROOT_OBJECT = 0x04,/* 包含内容是根对象(暂未使用)*/ TF_STATUS_CODE = 0x08,/* 表示data所描述的数据缓冲区内同是一个4bit状态吗*/ TF_ACCEPT_FDS = 0x10,/* 允许数据中包含文件描述符*/ };13、 flat_binder_object:
struct flat_binder_object { /* 8 bytes for large_flat_header. */ unsigned long type; //Binder对象的类型 unsigned long flags; //Binder对象的标志 /* 8 bytes of data. */ union { void *binder; /* local object */ signed long handle; /* remote object */ }; /* extra data associated with local object */ void *cookie; };14、binder_write_read:
/* * On 64-bit platforms where user code may run in 32-bits the driver must * translate the buffer (and local binder) addresses apropriately. */ /** \kernel\goldfish\drivers\staging\android\binder.h * 描述进程间通信过程中所传输的数据*/ struct binder_write_read { /** 输入数据——从用户空间传输到Binder驱动程序的数据, * 数据协议代码为命令协议代码,由BinderDriverCommandProtocol定义*/ signed long write_size; signed long write_consumed; // 记录从缓冲区取了多少字节的数据 unsigned long write_buffer; // 指向一个用户空间缓冲区的地址,里面的内容即为输入数据,大小由wirte_size指定 /** 输出数据,从Binder驱动程序,返回给用户空间的数据, * 数据协议代码为返回协议代码,由BinderDriverReturnProtocol定义*/ signed long read_size; signed long read_consumed; // 从read_buffer中读取的数据量 unsigned long read_buffer; // 指向用户缓冲区一个地址,里面保存输出数据 };15、BinderDriverCommandProtocol协议 :
/** \kernel\goldfish\drivers\staging\android\binder.h * BC命令协议*/ enum BinderDriverCommandProtocol { /** 这两个命令数据类型为binder_transaction_data,是最常用到的*/ // 一个Client进程请求目标进程执行某个事务时,会使用BC_TRANSACTION请求Binder驱动程序将通信数据传递到Server目标进程 // 使用者:Client进程 用处:传递数据 BC_TRANSACTION = _IOW('c', 0, struct binder_transaction_data), // 当Server目标进程处理完事务后,会使用BC_REPLY请求Binder将结果数据返回给Cliet源进程 // 使用者:Server进程, 用处:返回数据 BC_REPLY = _IOW('c', 1, struct binder_transaction_data), // 当前版本not support BC_ACQUIRE_RESULT = _IOW('c', 2, int), /** 数据类型为int,指向Binder内部一块内核缓冲区 * 目标进程处理完源进程事务后,会使用使用BC_FREE_BUFFER来释放缓冲区*/ BC_FREE_BUFFER = _IOW('c', 3, int), /** 通信数据为int类型,表示binder_ref的句柄值handle * 前面两个是增加/减少弱引用计数 * 后面两个是增加/减少强引用计数*/ BC_INCREFS = _IOW('c', 4, int), BC_DECREFS = _IOW('c', 7, int), BC_ACQUIRE = _IOW('c', 5, int), BC_RELEASE = _IOW('c', 6, int), /** Server进程完成增加强/弱引用计数后,会使用这两个命令通知Binder*/ BC_INCREFS_DONE = _IOW('c', 8, struct binder_ptr_cookie), BC_ACQUIRE_DONE = _IOW('c', 9, struct binder_ptr_cookie), // 当前不支持 BC_ATTEMPT_ACQUIRE = _IOW('c', 10, struct binder_pri_desc), /** Binder驱动程序请求进程注册一个线程到它的线程池中,新建立线程会使用BC_REGISTER_LOOPER来通知Binder其准备就绪*/ BC_REGISTER_LOOPER = _IO('c', 11), /** 一个线程自己注册到Binder驱动程序后,会使用BC_ENTER_LOOPER通知Binder其准备就绪*/ BC_ENTER_LOOPER = _IO('c', 12), /** 线程发出退出请求,这三条指令都没有通信数据*/ BC_EXIT_LOOPER = _IO('c', 13), /** 进程向Binder注册一个死亡通知*/ BC_REQUEST_DEATH_NOTIFICATION = _IOW('c', 14, struct binder_ptr_cookie), /** 进程取消之前注册的死亡通知*/ BC_CLEAR_DEATH_NOTIFICATION = _IOW('c', 15, struct binder_ptr_cookie), /** 数据指向死亡通知binder_ref_death的地址 * 进程获得Service组件的死亡通知后,会使用该命令通知Binder其已经处理完该死亡通知*/ BC_DEAD_BINDER_DONE = _IOW('c', 16, void *), };16、binder_ptr_cookie :
/**\binder.h * 可以用来描述一个Binder实体对象或一个Service组件的死亡通知 * 1、Binder实体对象:ptr,cookie见binder_node * 2、死亡通知:ptr指向一个Binder引用对象的句柄值 * cookie指向接收死亡通知的对象的地址*/ struct binder_ptr_cookie { void *ptr; void *cookie; };17、BinderDriverReturnProtocol :
enum BinderDriverReturnProtocol { /** Binder驱动程序处理进程发送的请求时,发生异常,在返回BR_ERROR通知该进程 * 数据类型为int,表示错误代码*/ BR_ERROR = _IOR('r', 0, int), /** 表示通知进程成功处理了该事务*/ BR_OK = _IO('r', 1), /** 对应前面的BC; * 1、 Client进程向Server进程发送通信请求(BC),Binder使用BR_TRANSACTION通知Server * 使用者:Binder驱动程序 用途:通知Server * 2、erver处理完请求使用BC通知Binder,Binder使用BR_REPLY通知Client * 使用者:Binder驱动程序用途:通知Client*/ BR_TRANSACTION = _IOR('r', 2, struct binder_transaction_data), BR_REPLY = _IOR('r', 3, struct binder_transaction_data), // 当前不支持 BR_ACQUIRE_RESULT = _IOR('r', 4, int), // Binder处理请求时,发现目标进程或目标线程已死亡,通知源进程 BR_DEAD_REPLY = _IO('r', 5), // Binder接收到BC_TRANSACTION或BC_REPLY时,会返回BR_TRANSACTION_COMPLETE通知源进程命令已接收 BR_TRANSACTION_COMPLETE = _IO('r', 6), // 增加减少强弱引用计数 BR_INCREFS = _IOR('r', 7, struct binder_ptr_cookie), BR_ACQUIRE = _IOR('r', 8, struct binder_ptr_cookie), BR_RELEASE = _IOR('r', 9, struct binder_ptr_cookie), BR_DECREFS = _IOR('r', 10, struct binder_ptr_cookie), // 当前不支持 BR_ATTEMPT_ACQUIRE = _IOR('r', 11, struct binder_pri_ptr_cookie), // Binder通知源进程执行了一个空操作;用以可以替换为BR_SPAWN_LOOPER BR_NOOP = _IO('r', 12), // Binder发现没有足够的线程处理请求时,会返回BR_SPAWN_LOOPER请求增加新的线程到Binder线程池中 BR_SPAWN_LOOPER = _IO('r', 13), // 当前不支持 BR_FINISHED = _IO('r', 14), /** void*指针指向用来接收Service组件死亡通知的对象的地址 * Binder监测到Service组件死亡时,使用BR_DEAD_BINDER通知Client进程 * Client请求注销之前的死亡通知,Binder完成后,返回BR_CLEAR_DEATH_NOTIFICATION_DONE*/ BR_DEAD_BINDER = _IOR('r', 15, void *), BR_CLEAR_DEATH_NOTIFICATION_DONE = _IOR('r', 16, void *), // 发生异常,通知源进程 BR_FAILED_REPLY = _IO('r', 17), };