android学习笔记 匿名Binder
来源:互联网 发布:js代码解压缩 编辑:程序博客网 时间:2024/06/05 03:38
对于已经建立好Binder通信的Client和server,server可以将一个Binder的引用传递给client,client可以通过这个引用来访问server。
那么这种匿名的访问是怎么建立起来的?在server被唤醒后为什么可以通过target-ptr找到bbinder呢?
答案就在第一次返回这个Binder的引用的时候,binder驱动保存了这个Binder实体的各种数据,创建了节点。
以surfaceflinger调用createConnection返回IsurfaceComposerClient为例:
- status_t BnSurfaceComposer::onTransact(
- uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
- {
- switch(code) {
- case CREATE_CONNECTION: {
- CHECK_INTERFACE(ISurfaceComposer, data, reply);
- sp<IBinder> b = createConnection()->asBinder();
- reply->writeStrongBinder(b);//关键
- //...
- }
我们进一步看下,parcel.cpp:
- status_t Parcel::writeStrongBinder(const sp<IBinder>& val)
- {
- return flatten_binder(ProcessState::self(), val, this);
- }
- status_t flatten_binder(const sp<ProcessState>& proc,
- const sp<IBinder>& binder, Parcel* out)
- {
- flat_binder_object obj;
- obj.flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;
- if (binder != NULL) {
- IBinder *local = binder->localBinder();//这里我们是由Client强转得到的,所以这里不是空,返回BBinder
- if (!local) {
- BpBinder *proxy = binder->remoteBinder();
- if (proxy == NULL) {
- LOGE("null proxy");
- }
- const int32_t handle = proxy ? proxy->handle() : 0;
- obj.type = BINDER_TYPE_HANDLE;
- obj.handle = handle;
- obj.cookie = NULL;
- } else {
- obj.type = BINDER_TYPE_BINDER;//关键,表示当前传入的类型,并将对象本身作为cookie传入。
- obj.binder = local->getWeakRefs();
- obj.cookie = local;
- }
- } else {
- obj.type = BINDER_TYPE_BINDER;
- obj.binder = NULL;
- obj.cookie = NULL;
- }
- return finish_flatten_binder(binder, obj, out);
- }
通过talkwithdriver----ioctrl---进入内核空间---也就是binder_ioctl中。
流程大略是binder_ioctl-----binder_thread_write------binder_transaction
在binder_transaction中会对传入的binder_transaction_data进行解析,打包成binder_transaction
- static void binder_transaction(struct binder_proc *proc,
- struct binder_thread *thread,
- struct binder_transaction_data *tr, int reply)
- {
- //....
- fp = (struct flat_binder_object *)(t->buffer->data + *offp);
- switch (fp->type) {//这里会对我们刚刚在reply里写入的数据进行解析
- case BINDER_TYPE_BINDER:
- case BINDER_TYPE_WEAK_BINDER: {//如果是传入了BBinder的实体
- struct binder_ref *ref;
- struct binder_node *node = binder_get_node(proc, fp->binder);//会进行查找,如果当前进程里没有节点,则会创建一个,node里保存了binder的实体地址和cookie,相当于是实名登记。
- if (node == NULL) {
- node = binder_new_node(proc, fp->binder, fp->cookie);
- if (node == NULL) {
- return_error = BR_FAILED_REPLY;
- goto err_binder_new_node_failed;
- }
- node->min_priority = fp->flags & FLAT_BINDER_FLAG_PRIORITY_MASK;
- node->accept_fds = !!(fp->flags & FLAT_BINDER_FLAG_ACCEPTS_FDS);
- }
- if (fp->cookie != node->cookie) {
- binder_user_error("binder: %d:%d sending u%p "
- "node %d, cookie mismatch %p != %p\n",
- proc->pid, thread->pid,
- fp->binder, node->debug_id,
- fp->cookie, node->cookie);
- goto err_binder_get_ref_for_node_failed;
- }
- ref = binder_get_ref_for_node(target_proc, node);//获取目标(client)进程对于node的引用
- if (ref == NULL) {
- return_error = BR_FAILED_REPLY;
- goto err_binder_get_ref_for_node_failed;
- }
- if (fp->type == BINDER_TYPE_BINDER)
- fp->type = BINDER_TYPE_HANDLE; //修改type为handle,等待client进程去读取,创建Bpbinder。
- else
- fp->type = BINDER_TYPE_WEAK_HANDLE;
- fp->handle = ref->desc;//传入handle值
- binder_inc_ref(ref, fp->type == BINDER_TYPE_HANDLE,
- &thread->todo);
- binder_debug(BINDER_DEBUG_TRANSACTION,
- " node %d u%p -> ref %d desc %d\n",
- node->debug_id, node->ptr, ref->debug_id,
- ref->desc);
- } break;
- //....
- }
在上述函数中,如果是第一次调用这个,binder驱动做的事里,最关键的是,在目标创建了这个BBinder的实体节点。
总的来说,在建立好Binder通信的连接(基于实名注册的Binder)后,server可以传递Binder对象的引用给client,大致的过程是:
server将Binder对象写入parcel,接着通过ioctrl和binder驱动通信,bidner驱动会对传入的对象进行检查,如果发现传入的type是binder,则会在当前进程(server对应的proc)查找是否有这个节点,如果没有就用传入的Binder实体在user空间指针和cookie(通常是BBinder本身)构造一个新的node,接着得到Binder实体的引用,存放在transaction_data中等待client去获取。
client拿到Binder的引用后,就可以通过这个BpBinder和server的BBinder进行通信了,和实名注册的Binder是一样的,不再赘述。
- android学习笔记 匿名Binder
- android学习笔记 匿名Binder
- android学习笔记--binder
- Android学习笔记--Binder
- Android学习笔记--Binder
- Android学习笔记--Binder
- Android 学习笔记 binder
- Android学习笔记--Binder
- Android学习笔记--Binder
- Android学习笔记--Binder
- Android学习笔记--Binder
- Android Binder学习笔记
- android—匿名binder
- Android中的Binder学习笔记
- Android Binder机制学习笔记之一
- Binder学习笔记---深入理解Android
- 学习笔记--《android内核剖析》binder
- 学习android内核-Binder笔记
- bootstrap学习笔记-第3章 表单
- 音频杂项
- Linux 网站收集
- spring学习
- 堆和栈的区别(转过无数次的文章)
- android学习笔记 匿名Binder
- 【正则表达式】input 只能输入汉字、数字、字母等
- 有关“类前置声明”和“包含头文件”的相关问题
- 坐标参数详解
- python获取指定日期的前n天或后n天日期
- Android ListView详解
- 显示所有用户,mysql的基本操作
- html5 动态存储 localStorage.name 和localStorage.setItem()的差别
- C与C++中struct使用的区别