Binder(七)系统服务注册流程总结

本文基于Android_9.0、kernel_3.18源码

通过Binder(三)到Binder(六)的相关文章,我们详细介绍了Binder服务启动、服务注册的流程;其中服务注册相当于servicemanager提供的一个方法,AMS在system_server进程中,AMS完成注册即通过binder完成了一次跨进程通信,我们再梳理一下整体流程。

Binder(七)系统服务注册流程总结

流程梳理

一、初始化

1、service_manager进程创建之后,会进行binder的初始化:
(1)通过binder_open打开dev/binder,创建binder_proc来记录进程信息,并通过mmap进行内存映射
(2)通过binder_become_context_manager注册为binder的管理者,即将自己赋值给全局变量全局变量binder_context_mgr_node
(3)通过binder_loop循环,等待消息,由于刚刚创建,没有进行中待处理任务,阻塞进程,等待唤醒

2、system_server进程创建后,也会进行binder初始化:
(1)通过ProcessState打开dev/binder,创建binder_proc来记录进程信息,并通过mmap进行内存映射
(2)通过开启新的线程,并调用IPCThreadState的joinThreadPool开启循环,等待接收消息,由于没有待处理的任务,该线程阻塞,等待唤醒。

二、进程通信

1、BpBinder的获取
binder通信,需要知道通信的目标是谁,在binder中定义binder_context_mgr_node的handle = 0,因此就通过handle = 0找到servicemanager,在BpBinder创建时持有了handle。

2、以AMS注册为例,数据发送
(1)通过Parcel将AMS数据包装,在此设置type为BINDER_TYPE_BINDER,并将AMS数据写入对应结构,再通过BpBinder的transact调用IPCThreadState的transact进行通信;
(2)在IPCThreadState的waitForResponse中,会调用binder驱动进行如下操作:
在第5步创建事务时,事物的数据地址直接通过地址偏移量计算出来,省去一次拷贝。

<1>查找/创建binder_thread
<2>找到servicemanager的binder_node
<3>查找/创建AMS的binder_node
<4>查找/创建AMS的binder_ref
<5>新建任务加入servicemanager队列中
<6>唤醒servicemanager进程
<7>创建任务告诉自己已经发送成功

(3)如上操作会唤醒servicemanager进程,servicemanager进程会对任务进行处理,同时发送回执

<1>找到AMS的binder_thread
<2>新建任务加入AMS队列中
<3>唤醒ssystem_server进程
<4>创建任务告诉自己已经发送成功

(4)第(3)步操作会唤醒system_server线程,system_server处理回执消息,退出waitForResponse,数据交互流程完毕。

数据结构

binder_proc

在binder驱动中,用来描述进程的上下文信息;每当进程打开文件节点/dev/binder时,binder驱动都会为这个进程创建一个binder_proc。

struct binder_proc {
    struct hlist_node proc_node;
    struct rb_root threads; // binder_thread红黑树
    struct rb_root nodes; // binder_node组成的红黑树
    struct rb_root refs_by_desc; // binder_ref组成的红黑树,根据句柄排序
    struct rb_root refs_by_node; // binder_ref组成的红黑树,根据binder_node排序
    int pid;
    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;

    // 通过buffer + user_buffer_offset便能计算出用户空间的地址
    void *buffer; // 物理内存在内核空间的起始位置
    ptrdiff_t user_buffer_offset; // 内核空间和用户空间的偏移量

    struct list_head buffers;
    struct rb_root free_buffers;
    struct rb_root allocated_buffers;
    size_t free_async_space;

    struct page **pages; // 映射的内存页数
    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;
};

binder_thread

描述线程相关的数据。

struct binder_thread {
    struct binder_proc *proc; // 进程信息
    struct rb_node rb_node;
    int pid;
    int looper; // 进程状态BINDER_LOOPER_STATE_ENTERED
    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;
};

binder_node

在binder驱动中,会为每一个服务创建一个binder_node,通过它可以找到真正提供服务的对象。

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; // binder_ref组成的链表
    int internal_strong_refs;
    int local_weak_refs;
    int local_strong_refs;
    binder_uintptr_t ptr; // 真正提供服务的对象地址,如AMS
    binder_uintptr_t cookie; // 真正提供服务的对象数据,如AMS数据
    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;
    unsigned min_priority:8;
    struct list_head async_todo;
};

binder_ref

binder驱动中,需要通过binder_ref找到binder_node(服务对应的实体),每个与binder_node对应的客户端都会创建一个binder_ref;


Binder(七)binder_ref和binder_node关系
struct binder_ref {
    /* Lookups needed: */
    /*   node + proc => ref (transaction) */
    /*   desc + proc => ref (transaction, inc/dec ref) */
    /*   node => refs + procs (proc exit) */
    int debug_id;
    struct rb_node rb_node_desc;
    struct rb_node rb_node_node;
    struct hlist_node node_entry;
    struct binder_proc *proc; // 进程
    struct binder_node *node; // binder_node
    uint32_t desc; // handle
    int strong;
    int weak;
    struct binder_ref_death *death;
};
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容