资讯专栏INFORMATION COLUMN

Binder进程间通讯学习笔记 [C++层及驱动层]

Winer / 716人阅读

摘要:内部是通过调用函数与驱动进行交互。函数既负责向驱动程序发送通讯请求,也负责接受来自驱动程序的通讯请求。线程池中的每一个线程都可以通过它来跟驱动程序进行交互对象中保存着内核缓冲区的用户地址。和目标进行进行进程间通讯。

基础知识

binder_init()初始化binder设备

binder_open()打开binder设备文件
2.1 初始化binder_proc结构体
2.2 将其加入到全局hash队列binder_procs中
2.3 创建/proc/binder/proc/

binder_mmap()进行内存映射
3.1 分配内核缓冲区
3.2 分配物理页面
3.3 将分配的内核缓冲区加入到进程的空闲内核缓冲区红黑树中
> 当Binder驱动程序需要将一块数据传输给进程时,可以先将数据保存在为该进程分配的一块内核缓冲区中
> 然后在把这块内核缓冲区的用户空间地址告诉进程
> 最后进程便可以访问到里面的数据了

binder内核缓冲区管理
4.1 分配内核缓冲区binder_alloc_buf()
4.2 释放内核缓冲区binder_free_buf()

类结构(User space)

Server组件/BnInterface/Binder本地对象/Binder实体对象

                    +-------+                                   
                    |RefBase|                                   
                    ++----+-+                                   
                     ^    ^                                     
               +-----+-+  |  +------------+                     
               |IBinder|  +--+ProcessState|                     
               +-----+-+     +-----+------+                     
                     ^             ^                            
+---------+        +-+-----+       |                            
|INTERFACE|        |BBinder|       |                            
+-+-------+        +-+--+--+       |                            
  ^                  ^  |          |                            
  |   +-----------+  | use   +-----+--------+                   
  +---+BnInterface+--+  +--> |IPCThreadState|                   
      +-----------+          +--------------+                   

Client组件/BpInterface/Binder代理对象/Binder引用对象

                   +-------+                      +------------+
                   |RefBase| <---+----------------+ProcessState|
                   +---+----     |                ------+------+
                       ^         |   +-------+          ^       
                       |         +---+IBinder|          |       
+---------+          +-+-------+     +--+----+          |       
|INTERFACE|          |BpRefBase|        ^               |       
+----+----+          +---+---+-+        |               |       
     ^                   ^   |          |               |       
     |   +-----------+   |  has    +----+---+           |       
     +---+BpInterface+---+   +---> |BpBinder|           |       
         +-----------+             +-----+--+           |       
                                         |              |       
                                        use    +--------+-----+ 
                                         +---> |IPCThreadState| 
                                               +--------------+ 

每一个使用了Binder的进程都有一个Binder线程池。每一个Binder线程内部都有一个IPCThreadState对象,可以通过IPCThreadState的静态方法self获取,并调用它的transact和Binder驱动程序交互。transact内部是通过调用talkWithDriver函数与驱动进行交互。talkWithDriver函数既负责向Binder驱动程序发送通讯请求,也负责接受来自Binder驱动程序的通讯请求。

IPCThreadState有一个成员变量mProcess,指向一个ProcessState对象。ProcessState对象负责初始化Binder设备(打开设备文件/dev/binder、将/dev/binder映射到内存)。Binder线程池中的每一个线程都可以通过它来跟Binder驱动程序进行交互(ProcessState对象中保存着内核缓冲区的用户地址)。

即:
* IPCThreadState负责接受和发送进程间通讯请求
* ProcessState负责Binder线程和Binder驱动程序之间的交互

交互过程
                              +                            
              Client Process  |  Server Process            
                              |                            
                              |                            
                +--------+    |    +-------+               
             +-->BpBinder|    |    |BBinder+------+        
             |  +------+-+    |    +--^----+      |        
 User Space  |     (1) |      |    (3)|           |        
+-----------------------------+---------------------------+
 Kernel Space|         |      |       |           |        
             | +-------v--+  (2)  +---+-------+   |        
             | |binder_ref+---+--->binder_node|   |        
          (5)| +----------+   |   +-----------+   |(4)     
             |                |                   |        
             |       +--------v---------+         |        
             +-------+binder_transaction<---------+        
                     +------------------+                  

一次的从Client到Server的通讯过程如下所示:
(1) BpClient向Binder驱动程序发起请求,Binder驱动程序根据BpClient传过来的handler找到对应的binder_ref。
(2) Binder驱动程序根据binder_ref找到对应的binder_node,并且创建一个binder_transaction来描述这次通讯。
(3) Binder驱动程序根据binder_node找到Server进程中的BBinder,将数据传给它。
(4) BBinder处理完成后,将结果返回给Binder驱动程序,驱动程序找到前面建立的binder_transaction。
(5) Binder驱动程序根据binder_transaction找到Client进程,进而找到BpBinder,将结果传给它处理。

若以transaction来描述一次client-server通讯,则如下图所示:

+------+                 +-------------+                     +------+
|Client|                 |Binder Driver|                     |Server|
+---+--+                 +-------+-----+                     +------+
    |                            |                               |   
    |      [BC_TRANSACTION]      |                               |   
    +--------------------------> |                               |   
    |        data(Parcel)        +---------------------+         |   
    |                            | find server process |         |   
    |                            | <-------------------+         |   
    |                            |                               |   
    | [BC_TRANSACTION_COMPLETE]  |       [BR_TRANSACTION]        |   
    | <--------------------------+-----------------------------> |   
    |                            |        data(Parcel)           |   
    |                            |                               |   
    +-----------------+          |              +----------------+   
    |wait for response|          |              |  process data  |   
    | <---------------+          |              +--------------> |   
    |                            |                               |   
    |                            |          [BC_REPLY]           |   
    |                            | <-----------------------------+   
    |        +-------------------+        result(Parcel)         |   
    |        |find client process|                               |   
    |        +-----------------> |                               |   
    |                            |                               |   
    |        [BR_REPLY]          |   [BR_TRANSACTION_COMPLETE]   |   
    | <--------------------------+-----------------------------> |   
    |      result(Parcel)        |                               |   
    |                            |              +----------------+   
    |                            |              | wait for next  |   
    |                            |              +--------------> |   
    |                            |                               |   
    +                            +                               +   
ServiceManager启动过程

ServiceManager是Binder机制的核心组件之一,扮演着Binder通讯中Context Manager的角色,通过负责管理Binder系统中的Service组件,并向Client组件提供获取Service Proxy对象的服务。

ServiceManager运行在独立进程中,与其通讯需采用Binder机制,所以ServiceManager算是一个特殊的Service组件。

ServiceManager由init进程负责启动,在系统启动的时候启动:

service servicemanager /system/bin/servicemanager
    user system
    critical
    onrestart restart zygote
    onrestart restart media

servicemanager以服务方式启动

critical表明当服务退出时,系统会立刻重启servicemanager。

onrestart参数表明,当servicemanager重启时,zygote和media也需要重启。

进程启动后,有以下三个初始化的步骤:

调用函数binder_open打开设备文件/dev/binder,以及将其映射到本进程的内存空间。

调用binder_become_context_manager将自己注册为Binder系统的context manager。

调用binder_loop来循环等待和处理Client进程的通讯请求。

获取Binder Proxy的过程

简略过程如下图所示:

+------+                 +-------------+              +-------------+
|Client|                 |Binder Driver|              |ServerManager|
+---+--+                 +-------+-----+              +----------+--+
    |                            |                               |   
    |      [BC_TRANSACTION]      |                               |   
    +--------------------------> |                               |   
    | target service name(Parcel)+-----------------------------+ |   
    |                            | find servermanager process  | |   
    |                            | <---------------------------+ |   
    |                            |                               |   
    | [BC_TRANSACTION_COMPLETE]  |       [BR_TRANSACTION]        |   
    | <--------------------------------------------------------> |   
    |                            |                               |   
    |                            |                               |   
    +-----------------+          | +-----------------------------+   
    |wait for handler |          | |[CHECK_SERVICE_TRANSACTION]  |   
    | <---------------+          | +---------------------------> |   
    |                            |                               |   
    |                            |          [BC_REPLY]           |   
    |                            | <-----------------------------+   
    |      +---------------------+      target service info      |   
    |      | create Binder Ref   |                               |   
    |      +-------------------> |                               |   
    |                            |                               |   
    |        [BR_REPLY]          |   [BR_TRANSACTION_COMPLETE]   |   
    | <--------------------------------------------------------> |   
    |      Binder Ref Handler    |                               |   
    |                            |              +----------------+   
    |                            |              | wait for next  |   
    |                            |              +--------------> |   
    +--------------------+       |                               |   
    | create Binder Proxy|       |                               |   
    | <------------------+       |                               |   
    |                            +                               +   
    |                                                                
    |           communicate with target Service                      
    +------------------------------------------------------------>   
    +                                                                

Client获取ServerManager的Proxy对象。

Client向ServerManager的Proxy对象请求获取目标service的handler。

ServerManager根据Client传入的service名称寻找目标service的信息,生成binder_ref,返回给client。

Client根据binder_ref生成proxy对象。

Client和目标Service进行进行进程间通讯。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/12316.html

相关文章

  • AIDL使用以及原理分析

    摘要:也就是说返回的对象有两种可能实际上有三种,还有一种是,和。相互不同通信,这是底层决定的。执行之后,驱动通过引用找到服务端进程引用,调用服务端对象中的方法,通过回调给客户端。AIDL使用以及IPC原理分析(进程间通信) 概要 为了大家能够更好的理解android的进程间通信原理,以下将会从以下几个方面讲解跨进程通讯信: 1. 必要了解的概念 2. 为什么要使用aidl进程间通信 3. 可能遇到...

    Tony_Zby 评论0 收藏0
  • Binder进程通讯学习笔记 [Java]

    摘要:服务的启动过程服务一般运行在系统进程或者应用程序进程中,需要在启动之前注册到。由于进程自带线程池,所以只需将注册到中即可不用初始化等。创建完毕后,通过方法注册到中。收到请求以后,将中的取出,并注册到内部。 ServiceManagerProxy对象的获取过程 各个类之间的关系图如下所示: +----------+ ...

    abson 评论0 收藏0
  • 02.Android之IPC机制问题

    摘要:中为何新增来作为主要的方式运行机制是怎样的机制有什么优势运行机制是怎样的基于通信模式,除了端和端,还有两角色一起合作完成进程间通信功能。 目录介绍 2.0.0.1 什么是Binder?为什么要使用Binder?Binder中是如何进行线程管理的?总结binder讲的是什么? 2.0.0.2 Android中进程和线程的关系?什么是IPC?为何需要进行IPC?多进程通信可能会出现什么问...

    Donne 评论0 收藏0
  • Android(IPC)进程通讯1:详解Binder由来?

    摘要:进程间通信方式虽然不同进程在用户空间不能直接进行通讯,但它们却是共享一份内核空间。系统为什么需要再实现一个进程间通信协议呢在移动设备上,的传输效率和可操作性很好。 完整原文:http://tryenough.com/android-... Android开发的进程间通讯,整个Android的应用都依赖于binder做底层通信机制。而Linux中提供的进程间通讯方式并没有binder机...

    cyrils 评论0 收藏0
  • Android(IPC)进程通讯1:详解Binder由来?

    摘要:进程间通信方式虽然不同进程在用户空间不能直接进行通讯,但它们却是共享一份内核空间。系统为什么需要再实现一个进程间通信协议呢在移动设备上,的传输效率和可操作性很好。 完整原文:http://tryenough.com/android-... Android开发的进程间通讯,整个Android的应用都依赖于binder做底层通信机制。而Linux中提供的进程间通讯方式并没有binder机...

    Tamic 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<