Binder机制的细节补充

作者: 优雨 | 来源:发表于2016-04-02 16:38 被阅读487次

    (1)Binder驱动的核心方法
    ①用户态程序调用内核驱动,需要陷入内核态,进行系统调用。当用户空间调用open方法,最终会调用binder驱动的binder_open方法,而mmap和ioctl方法也是同理,这些过程都是依赖于系统调用的。
    ②binder_open方法首先会创建binder_proc这个结构体对象,这个结构体主要包含了当前进程等信息,它用于管理IPC所需的各种信息并拥有其他结构体的根结构体。每次创建binder_proc的时候,都会将其加入到全局链表binder_procs中,并将其保存到文件指针filp的private_data中。
    ③binder_mmap方法主要功能为,在内核虚拟地址空间申请一块和用户虚拟内存相同大小的内存,然后在申请一个page大小的物理内存,并将其分别映射到内核虚拟地址空间和用户虚拟内存空间,从而实现用户空间buffer和内核空间buffer的同步操作功能。(计算方式是通过proc->user_buffer_offset,proc_addr = kernel_addr + user_buffer_offset)
    ④binder_ioctl是一个核心方法,它可以用来收发Binder的IPC数据,这个方法接受三个参数,第二和第三个参数决定函数具体执行什么操作,其中BINDER_WRITE_READ操作就是收发Binder的IPC数据的操作,它需要一个binder_write_read结构体作为参数,其包含了用户空间的数据ubuf。函数首先把用户空间数据拷贝到内核空间bwr,当bwr写缓存中有数据时,执行binder写操作(binder_thread_write方法);当bwr读缓存中有数据时,执行binder读操作(binder_thread_read方法)。最后将内核数据bwr拷贝到用户空间。
    (2)Binder内存机制高效的原因
    在(1)里我们知道通过binder_mmap方法,虚拟进程地址空间和虚拟内核地址空间都映射到了同一块物理内存空间,当Client端向Server发送数据时,Client先从自己的进程空间把IPC通信数据通过copy_from_user拷贝到内核空间,而Server端与内核共享数据,不再需要拷贝数据,而是通过内存地址空间的偏移量直接获得这个地址。整个过程只需要一次拷贝。
    (3)ServiceManager是整个Binder IPC的守护进程,启动ServiceManager的入口函数是service_manager.c中的main方法,主要分为如下几步:binder_open --> binder_becom_context_manager --> binder_loop
    其中binder_open方法打开binder驱动,并调用mmap方法分配128k的内存映射空间;binder_becon_context_manager通知binder程序使ServiceManager成为守护进程;binder_loop方法进入循环状态,等待Client端的请求。
    ①binder_open:首先通过open方法通过系统调用,陷入内核,打开binder设备驱动(对应于binder驱动层的binder_open方法,会创建binder_proc对象等),然后通过ioctl系统调用获取验证binder版本信息,最后通过系统调用,利用mmap方法进行内存映射(创建binder_buffer对象)
    ②binder_become_context_manager:这个方法内部是通过ioctl系统调用,根据参数BINDER_SET_CONTEXT_MGR,最终调用binder_ioctl_set_ctx_mgr方法的,该方法内部通过binder_new_node方法,给ServiceManager创建binder_node实体binder_context_mgr_node,这个实体是一个全局变量。创建好的binder_node会进行初始化,比如讲binder_proc加入到结构体的proc指针,创建async_todo,binder_work两个队列等。
    ③binder_loop:该方法首先通过binder_write方法(内部也是ioctl系统调用)将BC_ENTER_LOOPER命令发送给binder驱动,将binder_thread设为BINDER_LOOPER_STATE_ENTERED表示它进入了loop循环,之后的for无限循环里通过ioctl不断进行binder的读写过程,然后通过svcmgr_handler方法,进行binder信息的处理,包括注册服务,查找服务等(服务被保存在一个list里)
    (4)注册服务
    注册之前首先要通过defaultServiceManager方法获得BpServiceManager对象,同时会创建ProcessState对象和BpBinder对象,之后调用addService方法。该方法内部会调用BpBinder(这相当于一个代理类)的transact方法,参数里包括一个添加服务的命令。这个方法内部则会创建(如果不存在的话)并调用IPCThreadState的transact方法。IPCThreadState存储在ThreadLocalStorage中,每个线程都有自己的一个实例,其内部有一个mIn成员和mOut成员,用来接受和存储Binder设备的数据。这个transact方法最终会和binder驱动进行交互,首先他会为这个service创建一个binder_node实体,并为它创建一个引用,然后将待处理的事项加入到todo和work队列中,然后唤醒ServiceManager进行处理。ServiceManager最终会进行注册服务的过程(在loop中)。
    (5)获取服务
    获取一个服务的流程和注册服务类似,也需要获得BpServiceManager,进行BpBinder的transact,IPCThreadState的transact过程,ServiceManager最终会返回对应服务的Binder引用,客户端会根据这个引用和其包含的句柄创建一个BpBinder,从而可以通过这个代理对象和这个服务进行通信了。

    相关文章

      网友评论

        本文标题:Binder机制的细节补充

        本文链接:https://www.haomeiwen.com/subject/xmaylttx.html