struct list_head entry;
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_work 结构体,entry 的定义:
struct list_head {
struct list_head *next, *prev;
};
双向链表,用来存储所有的binder_work队列。type当然是枚举类型的,本来枚举其实从0开始的,这里显示的赋值BINDER_WORK_TRANSACTION = 1。那就理所当然的从1开始。type其实是binder_work的工作类型。后面会对这些类型做详细分析,我更觉得它作为工作状态来理解更好一些。
work分两种,进程work和线程work,分别记录在binder_proc和binder_thread的todo列表里.entry是用来把work加入到相应todo里的。而type则是描述work的性质。TRANSACTION类型的work就是后面将要说的transaction,android里进程之间普通的请求就是这个东西。
NODE类型的work是用于引用计数的,当binder_node(后面会提到什么是binder_node)的引用计数发生某些变化时,驱动就会往进程或者线程的work里添加这个binder_node的work。
DEAD_BINDER,DEAD_BINDER_AND_CLEAR,CLEAR_DEATH_NOTIFICATION这三种类型是用于死亡通知的驱动在处理各种work时,会考虑当前线程LOOPER状态(后面章节会解释),如果没有ENTERED或者REGISTERED的,便一定会把work添加到进程work里,否则很可能加到当前线程的work里,这个得看实际情况了。
binder 类型定义
#define B_PACK_CHARS(c1, c2, c3, c4) \
((((c1)<<24)) | (((c2)<<16)) | (((c3)<<8)) | (c4))
#define B_TYPE_LARGE 0x85
enum {
BINDER_TYPE_BINDER = B_PACK_CHARS('s', 'b', '*', B_TYPE_LARGE),
BINDER_TYPE_WEAK_BINDER = B_PACK_CHARS('w', 'b', '*', B_TYPE_LARGE),
BINDER_TYPE_HANDLE = B_PACK_CHARS('s', 'h', '*', B_TYPE_LARGE),
BINDER_TYPE_WEAK_HANDLE = B_PACK_CHARS('w', 'h', '*', B_TYPE_LARGE),
BINDER_TYPE_FD = B_PACK_CHARS('f', 'd', '*', B_TYPE_LARGE),
};
首先宏定义B_PACK_CHARS, c1 到c4 依次左移24,16,8,0位。不知道大家有没有发现规律,左移的间隔是8位,刚好一个字节。c1,c2,c3,c4 正好4个字节32位。继续宏定义B_TYPE_LARGE 为十六进制的0x85,占一个字节。然后枚举。在binder中枚举实在是太多啦,大家忍着看吧。枚举的5个类型正好是binder的5个不同类型。说白了就是五个宏定义,b应该是binder的缩写,代表本地类型,h是handle缩写,代表远端引用。看过对象和引用的应该了解的。w应该是WEAK_BINDER的代指,应该是指针强度的表示,那么s 指什么,强(strong)指针?大家想想。以上几个字母的含义是这是我猜的,不一定准确。fd就是很容易猜到的哦,就是文件。因此有:本地对象(BINDER_TYPE_BINDER,BINDER_TYPE_WEAK_BINDER),远程对象的引用(BINDER_TYPE_HANDLE,BINDER_TYPE_WEAK_HANDLE),文件(BINDER_TYPE_FD)。其实远程引用或者本地对象就是binder存在的两种方式,对于高层用户来说,他是不许要理清谁是本地谁是远程,因为提供了统一的接口。但是对于底层驱动来说,这是必须区分的了。这个类型定义就来干这件事情的。binder除了是个跨进程的指针之外,还能当做跨进程文件描述符用,FD类型就是干这个的
binder 对象
struct flat_binder_object {
/* 8 bytes for large_flat_header. */
unsigned long type;
unsigned long flags;
/* 8 bytes of data. */
union {
void *binder; /* local object */
signed long handle; /* remote object */
};
/* extra data associated with local object */
void *cookie;
};
我们把进程间传递的对象叫做binder对象,它的原型就是struct flat_binder_object。type是什么呢,你不知道?不可能。前面刚讲到额。五种就正好对应这里的type哦。flags指什么呢,什么什么什么呢?看看吧:
enum transaction_flags {
TF_ONE_WAY = 0x01, /* this is a one-way call: async, no return */
TF_ROOT_OBJECT = 0x04, /* contents are the component's root object */
TF_STATUS_CODE = 0x08, /* contents are a 32-bit status code */
TF_ACCEPT_FDS = 0x10, /* allow replies with file descriptors */
};
又是enum 头大了吧,不过幸好不复杂。看我一一道来. TF_ONE_WAY 便是单向传递,异步的。TF_ROOT_OBJECT,contents are the component's root object。什么东东?表示内容是一个组建的根对象,就是对应类型位本地对象的binder。TF_STATUS_CODE,又是什么呢?它表示的内容是一个32位的状态码,更容易理解的说法是一个远程对象的引用(即为句柄handle),又提到本地对象和远程引用的概念了,各位同学不要偷懒,还是要去查查的哦。TF_ACCEPT_FDS便是接受的是一个文件描述符,对应的类型为文件。在继续解释flags的7~0bits是用来设置binder_node的线程优先级的,在binder的实际应用中,远程进程的对binder的操作请求会由binder本地进程的一个线程完成,而这个优先级就是用来设置该线程处理这个binder事物时的优先级。flags的第八位 bit是用来表示这个binder是否接受文件描述符的,不支持文件描述符的binder是没法用binder类型为BINDER_TYPE_FD的。cookie在xx_BINDER类型(binder的两种类型)时就是binder_node的cookie,在xx_HANDLE类型时是null。