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驱动情景分析的更多相关文章

  1. 9.2 Binder系统_驱动情景分析_服务注册过程

    1. 几个重要结构体的引入给test_server添加一个goodbye服务, 由此引入以下概念: 进程间通信其实质也是需要三要素:源.目的.数据,源是自己,目的用handle表示:通讯的过程是源向实 ...

  2. Android : 跟我学Binder --- (4) 驱动情景分析

    目录: Android : 跟我学Binder --- (1) 什么是Binder IPC?为何要使用Binder机制? Android : 跟我学Binder --- (2) AIDL分析及手动实现 ...

  3. 9.5 Binder系统_驱动情景分析_transaction_stack机制

    参考文章:http://www.cnblogs.com/samchen2009/p/3316001.html test_server服务进程可能有多个线程,而在发送数据的时候handle只表示了那个进 ...

  4. dvwa 源码分析(二) --- dvwaPage.inc.php分析

    在setup.php中,包含了这个文件,所以这里分析这个文件. <?php if( !defined( 'DVWA_WEB_PAGE_TO_ROOT' ) ) { define( 'DVWA S ...

  5. 9.3 Binder系统_驱动情景分析_服务获取过程

    4. 服务获取过程 test_client客户端: (1)在用户态先构造name=“hello”的数据(服务的名字是hello),调用ioctl发送数据给service_manager(handle= ...

  6. 9.6 Binder系统_驱动情景分析_server的多线程实现

    当多个client对server发出请求的时候,如果server忙不过来的时候会创建多线程来处理请求 那么忙不过来由谁来判断? server进程有个binder_proc结构体,其里面有todo链表( ...

  7. 9.4 Binder系统_驱动情景分析_服务使用过程

    5. 服务使用过程 test_client进程: 用户态: (1)已结获得了“hello”服务,handle=1; (2)构造数据:code(那个函数)和函数参数 (3)发送ioctl后进入内核态,先 ...

  8. Android事件分发机制浅谈(二)--源码分析(ViewGroup篇)

    上节我们大致了解了事件分发机制的内容,大概流程,这一节来分析下事件分发的源代码. 我们先来分析ViewGroup中dispatchTouchEvent()中的源码 public boolean dis ...

  9. Android 学习笔记之AndBase框架学习(二) 使用封装好的进度框,Toast框,弹出框,确认框...

    PS:渐渐明白,在实验室呆三年都不如在企业呆一年... 学习内容: 1.使用AbActivity内部封装的方法实现进度框,Toast框,弹出框,确认框...   AndBase中AbActivity封 ...

随机推荐

  1. ServiceStack.Redis 使用链接池方法

    PooledRedisClientManager 1.RedisManage.cs public static class RedisManager { private static PooledRe ...

  2. C语言-知识点及学习路线

    最近进行了为期两周的C语言培训,把几年前学过的C语言又重新学习了一遍,然后根据学习的内容和过程,总结了一下学习路线.这是基本的C语言学习路线,相当于编程语言类的基础,再根据自己究竟是要做单片机开发,还 ...

  3. android开发学习——day3

    关于android开发的详细过程了解 Android App程序的四种重要组成类型:1.Activity 2.Service 3.Content Provider 4.Broadcast Receiv ...

  4. 【python之路12】三元运算符(if)

    1.三元运算符条件语句 普通if条件是这样写的: n = 1 if n > 0: st = '大于0' else: st = '小于等于0' print(st) 三元运算符的写法: n = 1 ...

  5. Thinkphp代码生成工具 ThinkphpHelper

    支持MySQL 和 sqlite数据库,快速构建项目原型,直接生成前后台CRUD代码片段,还可根据需要自行定制代码模板,减少重复劳动. 写这个东西的原因是因为我最近沮丧的发现很多时候我都在做重复的事情 ...

  6. swift Alamofire请求数据与SwiftJson解析

    一直在研究swift 程序最重要的是什么???答案当然是数据啦.  数据对一个程序的影响有多大自己想去吧!!!如果你非要说不重要,那你现在就可以关网页了  哈哈哈哈哈 我呢  swift新手  菜鸟一 ...

  7. Spring mvc基本原理

    http://blog.csdn.net/xtu_xiaoxin/article/details/8796499 http://www.cnblogs.com/wawlian/archive/2012 ...

  8. Canvas scale- 缩放

    可以进行坐标缩放,设为负值可以翻转图片: <!DOCTYPE html> <html lang="en"> <head> <meta ch ...

  9. 深入React事件系统(React点击空白部分隐藏弹出层;React阻止事件冒泡失效)

    只关注括号内问题的同学,可直接跳转到蓝字部分.(标题起的有点大,其实只讨论一个问题) 两个在React组件上绑定的事件,产生冲突后,使用e.stopPropagation(),阻止冒泡,即可防止事件冲 ...

  10. GreenOpenPaint的实现(一)基本框架

    Win7下的MSPaint是Ribbon的典型运行.这种SDI程序对于图像处理来说是很适合的.利用春节时间,基于之前的积累,我实现GreenOpenPaint,主要就是模拟MSPaint的界面,实现出 ...