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[];
} 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[];
} data;
};
Binder 驱动(三)的更多相关文章
- Android - Binder驱动
以下资料摘录整理自老罗的Android之旅博客,是对老罗的博客关于Android底层原理的一个抽象的知识概括总结(如有错误欢迎指出)(侵删): http://blog.csdn.net/luosh ...
- Binder机制,从Java到C (10. Binder驱动)
Binder驱动的代码都在kernel里面,这里就简单讲一下里面涉及到的几个东西: 1.MemoryBinder其实本质上就是一中数据传输方式,这种方式是通过binder driver实现的. 我们知 ...
- Android系统--Binder系统具体框架分析(二)Binder驱动情景分析
Android系统--Binder系统具体框架分析(二)Binder驱动情景分析 1. Binder驱动情景分析 1.1 进程间通信三要素 源 目的:handle表示"服务",即向 ...
- Android Binder实现浅析-Binder驱动
简介 Android是如何实现跨进程通信的,大家熟悉的Binder是什么,怎么设计的,进程间的数据如何发送接收的.本文将以及解析,并对Binder驱动实现.Native层实现.Java层实现三块做一个 ...
- [Binder深入学习一]Binder驱动——基础数据结构
具体代码路径: kernel/drivers/staging/android/binder.c kernel/drivers/staging/android/binder.h /* * binder_ ...
- Android面试官:说说你对 Binder 驱动的了解?
面试官提了一个问题:说说你对 binder 驱动的了解.这个问题虽有些 "面试造火箭" 的无奈,可难点就是亮点.价值所在,是筛选面试者的有效手段.如果让你回答,你能说出多少呢?我们 ...
- android binder 机制三(匿名Service)
什么是匿名Service?凡是没有到ServiceManager上注冊的Service,都是匿名Service. 还是拿上一篇的样例来举例,看代码: status_t MediaPlayer::set ...
- 【iCore4 双核心板_ARM】例程一:ARM驱动三色LED
实验原理: 通过STM32的三个GPIO驱动一个三色LED,引脚PB2接红色LED(ARM_LEDR), 引脚PA9接蓝色LED(ARM_LEDB),引脚PA10接绿色LED(ARM_LEDG), ...
- 【iCore1S 双核心板_ARM】例程一:ARM驱动三色LED
实验原理: 通过STM32的三个GPIO驱动一个三色LED,引脚PF3接蓝色LED(ARM_LEDB), 引脚PF4接绿色LED(ARM_LEDG),引脚PF5接红色LED(ARM_LEDR), G ...
随机推荐
- Locality preserving hashing for fast image search: theory and applications
Is there any Java library that provides an implementation (or several) of a Locality Preserving Hash ...
- Javascript 的addEventListener()及attachEvent()对比
Mozilla中: addEventListener的使用方式: target.addEventListener(type, listener, useCapture); target: 文档节点.d ...
- NIOS II 自定义IP核编写基本框架
关于自定义IP .接口 a.全局信号 时钟(Clk),复位(reset_n) b.avalon mm slave 地址(as_address) 片选(as_chipselect /as_chipsel ...
- XJOI 3601 技能(贪心+二分)
题目描述: 有一个oier,他有n个算法技能,每个技能有一个水平值,每个技能的水平上限都是A,设这个oier有cnt个技能达到了A, 设所有水平值的最小值为mi,那么这个oier的战斗力为cnt×Cf ...
- PHP开发实用-阿里短信服务(Short Message Service)
步骤 1 使用阿里云短信服务正常发短信需要 短信签名 短信模板 1申请短信签名 根据用户属性来创建符合自身属性的签名信息.企业用户需要上传相关企业资质证明,个人用户需要上传证明个人身份的证明. ...
- java 异步调用与多线程
异步与多线程的区别 一.异步和多线程有什么区别?其实,异步是目的,而多 线程是实现这个目的的方法.异步是说,A发起一个操作后(一般都是比较耗时的操作,如果不耗时的操作 就没有必要异步了),可以继续自顾 ...
- Consul .netcore
0)基本概念 consul常用于服务发现 [微服务] web_Api \ \ ->注册服务 raft选举le ...
- 使用SQL Delta.v5.1.1.98.破解版同步数据结构
概述 本篇文章主要介绍SQL DELTA的简单使用.为了能够更加明了的说明其功能,本文将通过实际项目中的案例加以介绍. 1. SQLDELTA简介 SQLDELTA是一款便捷实用的数据库管理工具.使用 ...
- python3.7.0安装
如何安装Python的操作步骤: 1.第一步先去python的官方网站下载python的安装包 地址:https://www.python.org/downloads/ 根据自己的系统选择对应的安装包 ...
- Android 开发怎样做代码加密或混淆?
欢迎访问网易云社区,了解更多网易技术产品运营经验. 在大公司怎么做android代码混淆的?发现他们的软件用apktool反编译居然没看到classes.dex文件和当前安卓APP加固到底该如何做到防 ...