Binder 驱动
Posted mingfeng002
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Binder 驱动相关的知识,希望对你有一定的参考价值。
Binder 驱动是 Binder 的最终实现, ServiceManager 和 Client/Service 进程间通信最终都是由 Binder 驱动投递的。
Binder 驱动的代码位于 kernel 代码的 drivers/staging/android 目录下。主文件是 binder.h 和 binder.c
Binder 驱动的逻辑图
进程间传输的数据被称为 Binder 对象,它是一个 flat_binder_object,结构如下
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; };
其中 类型 type 描述了 Binder 对象的类型,包含 BINDER
(本地对象)、HANDLE
(远程对象)、 FD
三大类(五种)
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), };
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 */ };
而 flat_binder_object
中的 union 联合体 就是要传输的数据,当类型为 BINDER
时, 数据就是一个本地对象 *binder,而类型为 HANDLE
时,数据则是一个远程对象 handle。
当 flat_binder_object
在进程间传递时, Binder 驱动会修改它的类型和数据,交换的代码参考 binder_transaction 的实现。
该如何理解本地 BINDER
对象和远程 HANDLE
对象呢?其实它们都代表同一个对象,不过是从不同的角度来看。举例来说,假如进程 RemoteService
有个对象 mBinder,对于 RemoteService
来说,mBinder
就是一个本地的 BINDER
对象;如果进程 app
通过 Binder 驱动访问 RemoteService
的 mBinder
对象,对于 app
来说, mBinder
就是一个 HANDLE
。因此,从根本上来说 handle
和 binder
都指向 RemoteService
的 mBinder
。本地对象还可以带有额外的数据,保存在 cookie 中。
Binder 驱动直接操作的最外层数据结构是 binder_transaction_data, Binder 对象 flat_binder_object
被封装在 binder_transaction_data 结构体中。
binder_transaction_data
数据结构才是真正传输的数据,其定义如下
struct binder_transaction_data { /* The first two are only used for bcTRANSACTION and brTRANSACTION, * identifying the target and contents of the transaction. */ union { size_t handle; /* target descriptor of command transaction */ void *ptr; /* target descriptor of return transaction */ } target; void *cookie; /* target object cookie */ unsigned int code; /* transaction command */ /* General information about the transaction. */ unsigned int flags; pid_t sender_pid; uid_t sender_euid; size_t data_size; /* number of bytes of data */ size_t offsets_size; /* number of bytes of offsets */ /* If this transaction is inline, the data immediately * follows here; otherwise, it ends with a pointer to * the data buffer. */ union { struct { /* transaction data */ const void *buffer; /* offsets from buffer to flat_binder_object structs */ const void *offsets; } ptr; uint8_t buf[8]; } data; };
flat_binder_object
就被封装在 *buffer中,其中的 unsigned int code; 则是传输命令,描述了 Binder 对象执行的操作。
1. binder 设备的创建
device_initcall() 函数是内核加载驱动的入口函数,我们先来看这个函数的调用过程。
static struct miscdevice binder_miscdev = { .minor = MISC_DYNAMIC_MINOR, .name = "binder", .fops = &binder_fops }; static int __init binder_init(void) { int ret; ... ret = misc_register(&binder_miscdev); ... return ret; } device_initcall(binder_init);
可以看出 binder_init() 使用 misc_register()
函数创建了 binder 设备。从 misc_register(&binder_miscdev); 及 .name = "binder" 可以看出, binder 向 kernel 注册了一个 /dev/binder
的字符设备,而文件操作都在 binder_fops 结构体中定义。
static const struct file_operations binder_fops = { .owner = THIS_MODULE, .poll = binder_poll, .unlocked_ioctl = binder_ioctl, .mmap = binder_mmap, .open = binder_open, .flush = binder_flush, .release = binder_release, };
从上面 binder_fops
结构体可以看出,主要的操作是 binder_ioctl()
binder_mmap()
binder_open()
等函数实现的。
2. ServiceManager 服务的注册
binder协议和数据结构
binder.h 文件中定义了 binder 协议和重要的数据结构。
首先在 enum 中定义了 binder 处理的类型,引用或是句柄
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), };
下面这段宏定义则是在 ioctl
函数调用时可用的具体命令。
#define BINDER_WRITE_READ _IOWR(‘b‘, 1, struct binder_write_read) #define BINDER_SET_IDLE_TIMEOUT _IOW(‘b‘, 3, int64_t) #define BINDER_SET_MAX_THREADS _IOW(‘b‘, 5, size_t) #define BINDER_SET_IDLE_PRIORITY _IOW(‘b‘, 6, int) #define BINDER_SET_CONTEXT_MGR _IOW(‘b‘, 7, int) #define BINDER_THREAD_EXIT _IOW(‘b‘, 8, int) #define BINDER_VERSION _IOWR(‘b‘, 9, struct binder_version)
在 BinderDriverReturnProtocol 和 BinderDriverCommandProtocol 中 则分别定义了 客户端调用 和 服务端 返回的命令。
binder_ioctl() 函数
用户态程序调用 ioctl
系统函数向 /dev/binder
设备发送数据时,会触发 binder_ioctl
函数响应。
binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) 函数用来处理
Binder 在头文件中只要定义了两个数据类型, 一个是 binder_write_read
struct binder_write_read { signed long write_size; /* bytes to write */ signed long write_consumed; /* bytes consumed by driver */ unsigned long write_buffer; signed long read_size; /* bytes to read */ signed long read_consumed; /* bytes consumed by driver */ unsigned long read_buffer; };
以及 binder_transaction_data
struct binder_transaction_data { /* The first two are only used for bcTRANSACTION and brTRANSACTION, * identifying the target and contents of the transaction. */ union { size_t handle; /* target descriptor of command transaction */ void *ptr; /* target descriptor of return transaction */ } target; void *cookie; /* target object cookie */ unsigned int code; /* transaction command */ /* General information about the transaction. */ unsigned int flags; pid_t sender_pid; uid_t sender_euid; size_t data_size; /* number of bytes of data */ size_t offsets_size; /* number of bytes of offsets */ /* If this transaction is inline, the data immediately * follows here; otherwise, it ends with a pointer to * the data buffer. */ union { struct { /* transaction data */ const void *buffer; /* offsets from buffer to flat_binder_object structs */ const void *offsets; } ptr; uint8_t buf[8]; } data; };
以上是关于Binder 驱动的主要内容,如果未能解决你的问题,请参考以下文章
Binder 机制分析 Android 内核源码中的 Binder 驱动源码 binder.c ( googlesource 中的 Android 内核源码 | 内核源码下载 )