Android系统--Binder系统具体框架分析(二)Binder驱动情景分析
Android系统--Binder系统具体框架分析(二)Binder驱动情景分析
1. Binder驱动情景分析
1.1 进程间通信三要素
源
目的:handle表示“服务”,即向实现该“服务”的进程发送数据;handle是“服务”的引用
int binder_call(struct binder_state *bs, struct binder_io *msg, struct binder_io *reply, uint32_t target, uint32_t code)
// bs:驱动信息
// msg:含有服务的名字
// reply:它会含有回复的数据
// target:表示目的
// code:调用的函数
- 数据
1.2 handle的深入剖析
1.2.1 涉及handle的重要结构体
Binder中的handle:进程A对进程B提供的服务S的引用
- 引用:通过struct binder_ref结构体关联服务节点
struct binder_ref {//就是 refs_by_desc、refs_by_node 这两个引用树种的数据结构.
int debug_id;
struct rb_node rb_node_desc;//连接des的引用树.
struct rb_node rb_node_node;//连接node的引用树.
struct hlist_node node_entry;
struct binder_proc *proc; //该binder引用所属的进程,
struct binder_node *node;//和远程的binder实体binder_node关联的地方.相对应.
uint32_t desc;
int strong;
int weak;
struct binder_ref_death *death;
};
- 服务:创建binder_node服务节点,指向进程B
struct binder_node {
int debug_id;
struct binder_work work;
union {
struct rb_node rb_node;
struct hlist_node dead_node;
};
struct binder_proc *proc;
struct hlist_head refs;
int internal_strong_refs;
int local_weak_refs;
int local_strong_refs;
void __user *ptr;
void __user *cookie;
unsigned has_strong_ref : 1;
unsigned pending_strong_ref : 1;
unsigned has_weak_ref : 1;
unsigned pending_weak_ref : 1;
unsigned has_async_transaction : 1;
unsigned accept_fds : 1;
int min_priority : 8;
struct list_head async_todo;
};
- 进程B:用结构体struct binder_proc表示
struct binder_proc {
struct hlist_node proc_node;//连入总链表的点.
struct rb_root threads; // 红黑树的节点,(不理解红黑树结构,暂时就当成该存储数据的地方即可)
struct rb_root nodes;
struct rb_root refs_by_desc;
struct rb_root refs_by_node;
int pid; //进程的id.
struct vm_area_struct *vma;
struct mm_struct *vma_vm_mm;
struct task_struct *tsk;
struct files_struct *files;
struct hlist_node deferred_work_node;
int deferred_work;
void *buffer;//表示要映射的物理内存在内核空间中的起始位置
//内核使用的虚拟地址与进程使用的虚拟地址之间的差值,即如果某个物理页面在内核空间中对应的虚拟地址是addr的话,
//那么这个物理页面在进程空间对应的虚拟地址就为addr + user_buffer_offset
ptrdiff_t user_buffer_offset;
struct list_head buffers;//通过mmap映射的内存空间.
struct rb_root free_buffers;//空闲的binder_buffer通过成员变量rb_node连入到struct binder_proc中的free_buffers表示的红黑树中去,
struct rb_root allocated_buffers;//正在使用的binder_buffer通过成员变量rb_node连入到struct binder_proc中的allocated_buffers表 示的红黑树中去。
size_t free_async_space;
struct page **pages;// struct page 用来描述物理页面的数据结构
size_t buffer_size; //表示要映射的内存的大小.
uint32_t buffer_free;
struct list_head todo;
wait_queue_head_t wait;
struct binder_stats stats;
struct list_head delivered_death;
int max_threads;
int requested_threads;
int requested_threads_started;
int ready_threads;
long default_priority;
struct dentry *debugfs_entry;
};
- 真实场景中有多个客户端服务对进程B要求服务,进程B创建多个线程提供服务,用struct rb_root结构体(红黑树)管理线程,线程用struct binder_thread描述
struct binder_thread {
struct binder_proc *proc; //当前线程所属的进程。
struct rb_node rb_node; //来连入binder_proc的threads红黑树.
int pid;
int looper;//表示线程的状态 就是上面enum的类型。
struct binder_transaction *transaction_stack; //表示线程正在处理的事务
struct list_head todo; //表示发往该线程的数据列表待处理的一次通信事务.
uint32_t return_error; /* Write failed, return error code in read buf */
uint32_t return_error2; /* Write failed, return error code in read */
/* buffer. Used when sending a reply to a dead process that */
/* we are also waiting on */
wait_queue_head_t wait; //用来阻塞线程等待某个事件的发生
struct binder_stats stats; //用来保存一些统计信息
};
1.2.2 解析handle对Binder节点操作流程
(1)server传入一个flat_binder_object结构体给驱动,在内核态驱动里为每一个服务创建binder_node,biner_node.proc关联描述进程的结构体
(2)ServiceManager 在驱动中创建binder_ref结构体,引用binder_node服务节点
在用户态创建服务链表(name,handle)
binder_ref.desc关联handle
(3)client向ServiceManager传入name查询对应服务
(4)servicemanager返回hanle给驱动程序
(5)驱动程序在servicemanager的binder_ref红黑树中根据handle找到binder_ref结构体,在根据binder_ref.node找到binder_node结构体,最后为client创建新的binder_ref,并关联找到的binder_node节点,他的结构体成员desc从1开始,驱动返回的desc给client,即为handle。
(6)总结client如何得到hanled:驱动根据handle找到binder_ref结构体->binder_node->进程server
1.3 client与server数据传输过程
- client端(先读后写)
(1)client构造数据,调用ioctl发送数据
(2)驱动根据handle找到server进程
(3)将数据存入进程的binder_proc.todo
(4)等待唤醒(等待server传回数据)
(5)被唤醒
(6)从todo链表中取出数据,返回用户空间
- server端(先写后读)
(1)等待数据传入,休眠
(2)client有数据写入,唤醒
(3)从binder_proc.todo链表当中取出数据,返回用户空间
(4)进行数据处理
(5)将结果写给client,也是放入client中的binder_proc.todo
(6)唤醒client
1.4 数据复制详解
- 一般方法(需要两次)
(1)client构造数据
(2)client:copy_from_user
(3)server:copy_to_user
(4)用户态处理
- Binder方法(一次)
(1)server mmap:用户态可以直接访问驱动中的某块内存
(2)client构造数据:copy_from_user,存放在server mmap映射的内存
(3)server直接获取使用数据
- 描述一段通过mmap映射的内存空间--结构体binder_buffer来描述
struct binder_buffer {
struct list_head entry; //连入 binder_proc的buffers
//空闲的binder_buffer通过成员变量rb_node连入到binder_proc中的free_buffers表示的红黑树中.
//正在使用的binder_buffer通过成员变量rb_node连入到binder_proc中的allocated_buffers表示的红黑树中去。
struct rb_node rb_node;
unsigned free:1; //每一个binder_buffer又分为正在使用的和空闲的,通过free成员变量来区分.
unsigned allow_user_free:1;
unsigned async_transaction:1;
unsigned debug_id:29;
struct binder_transaction *transaction;
struct binder_node *target_node;
size_t data_size;
size_t offsets_size;
uint8_t data[0];
};
注:一次数据复制是针对传输数据,其binder_write_read还是需要两次复制。client调用ioctl发送数据,ioctl发送的是binder_write_read结构,其结构体中的成员指向传送数据。
1.5 改进binder分析一代码
- 注册服务,直接将函数作为指针注册
/* add service */
ret = svcmgr_publish(bs, svcmgr, "hello", hello_service_handler);
//注册
if (ret) {
fprintf(stderr, "failed to publish hello service\n");
return -1;
}
ret = svcmgr_publish(bs, svcmgr, "goodbye", goodbye_service_handler);
if (ret) {
fprintf(stderr, "failed to publish goodbye service\n");
}
- 将被调用函数指向handler,返回handler函数
int test_server_handler(struct binder_state *bs,struct binder_transaction_data *txn,struct binder_io *msg, struct binder_io *reply)
{
int (*handler)(struct binder_state *bs,struct binder_transaction_data *txn,struct binder_io *msg,struct binder_io *reply); //构造处理方法
handler = (int (*)(struct binder_state *bs,struct binder_transaction_data *txn,struct binder_io *msg,struct binder_io *reply))txn->target.ptr; //根据txn->target.ptr返回处理相应方法
return handler(bs, txn, msg, reply); //返回所调用的处理方法
}
Android系统--Binder系统具体框架分析(二)Binder驱动情景分析的更多相关文章
- 9.2 Binder系统_驱动情景分析_服务注册过程
1. 几个重要结构体的引入给test_server添加一个goodbye服务, 由此引入以下概念: 进程间通信其实质也是需要三要素:源.目的.数据,源是自己,目的用handle表示:通讯的过程是源向实 ...
- Android : 跟我学Binder --- (4) 驱动情景分析
目录: Android : 跟我学Binder --- (1) 什么是Binder IPC?为何要使用Binder机制? Android : 跟我学Binder --- (2) AIDL分析及手动实现 ...
- 9.5 Binder系统_驱动情景分析_transaction_stack机制
参考文章:http://www.cnblogs.com/samchen2009/p/3316001.html test_server服务进程可能有多个线程,而在发送数据的时候handle只表示了那个进 ...
- dvwa 源码分析(二) --- dvwaPage.inc.php分析
在setup.php中,包含了这个文件,所以这里分析这个文件. <?php if( !defined( 'DVWA_WEB_PAGE_TO_ROOT' ) ) { define( 'DVWA S ...
- 9.3 Binder系统_驱动情景分析_服务获取过程
4. 服务获取过程 test_client客户端: (1)在用户态先构造name=“hello”的数据(服务的名字是hello),调用ioctl发送数据给service_manager(handle= ...
- 9.6 Binder系统_驱动情景分析_server的多线程实现
当多个client对server发出请求的时候,如果server忙不过来的时候会创建多线程来处理请求 那么忙不过来由谁来判断? server进程有个binder_proc结构体,其里面有todo链表( ...
- 9.4 Binder系统_驱动情景分析_服务使用过程
5. 服务使用过程 test_client进程: 用户态: (1)已结获得了“hello”服务,handle=1; (2)构造数据:code(那个函数)和函数参数 (3)发送ioctl后进入内核态,先 ...
- Android事件分发机制浅谈(二)--源码分析(ViewGroup篇)
上节我们大致了解了事件分发机制的内容,大概流程,这一节来分析下事件分发的源代码. 我们先来分析ViewGroup中dispatchTouchEvent()中的源码 public boolean dis ...
- Android 学习笔记之AndBase框架学习(二) 使用封装好的进度框,Toast框,弹出框,确认框...
PS:渐渐明白,在实验室呆三年都不如在企业呆一年... 学习内容: 1.使用AbActivity内部封装的方法实现进度框,Toast框,弹出框,确认框... AndBase中AbActivity封 ...
随机推荐
- SVN下载分支、合并分支
http://www.cnblogs.com/armyfai/p/3985660.html(不知道实际工作中怎么使用,有好多步骤感觉不是太理解) 从远处把库fork到本地,会有一个库文件夹 服务器库结 ...
- 思迅/泰格/科脉/收银软件/商超软件数据库修复解决断电造成损坏的mdb\dat文件SQL数据库 置疑 修复 恢复
拥有专业管理软件数据库修复技术工程师,专业提供管家婆.美萍.思迅.科脉等管理软件技术服务,电脑维修\重装系统技 术服务.无法登陆打不开等出错问题处理(连接失败,请输入正确的服务器名,SQL Serve ...
- bzoj1449————2016——3——14
传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=1449 题目简述: Description Input Output 一个整数表示联盟里所有球 ...
- Xcode 之 snippet 代码重用
1. 选中代码 2. 拖入xcode 右下侧的 snippet 区域 3. 修改名称 4. 修改快捷输入 (shortcut) 5. <#content#> ,可选修改项
- JAVA文件的两种读取方法和三种写入方法
在使用java对文件进行读写操作时,有多种方法可以使用,但不同的方法有不同的性能. 此文对常用的读写方法进行了整理,以备不时之需. 1.文件的读取 主要介绍两种常用的读取方法.按行读取和按字符块读取. ...
- php session 生命周期代码实例
php session 生命周期代码实例 我们为什么需要Session,就是因为我们需要存储各个用户的状态数据.那么试问,如果由你来设计解决这个需求的方案,那么也许你会设置这样一个数据 ...
- jquery的动画函数animate()讲解一
jquery animate 动画效果使用说明 animate( params, [duration], [easing], [callback] ) 用于创建自定义动画的函数. 这个函数的关键在于指 ...
- 响应的系统设置的事件——Configuration类简介
Configuration类专门用于描述手机设备上的配置信息,这些配置信息既包括用户特定的配置项,也包括系统的动态设置配置. 程序可调用Activity的如下方法来获取系统的Configuration ...
- 我用Cocos2d-x模拟《Love Live!学院偶像祭》的Live场景(四)
[前言和思路整理] 千呼万唤Shǐ出来!最近莫名被基友忽悠着进舰坑了,加上要肝LL活动,又碰上公司项目紧张经常加班,这一章发得比以往时候来得更晚一些,抱歉啊. 上一章我们实现了BeatObjectMa ...
- MongoDB安装环境搭建
Mongodb的默认端口号27017 _id是全局唯一值,不要去给这个列赋值,默认是唯一的,如果赋值,列入有两列的_id:2,则会报冲突不能插入 [root@HE4 ~]# tar xvf mongo ...