1.6 Binder机制

1 minute read

1.6.1 Binder驱动

  • 流程
    1. init(), 创建/dev/binder设备节点, 调用binder_init(), 注册misc设备, 即调用misc_register()
    2. open()获取Binder Driver的文件描述符, binder_open(), 打开binder驱动设备, 创建binder_proc对象, 保存当前进程信息
    3. 通过mmap(), 在内核分配内存, binder_mmap()在内核虚拟地址空间申请一块与用户虚拟内存相同大小的内存, 再申请一个page大小的物理内存, 将同一块物理内存分别映射到内核虚拟地址空间和用户虚拟内存空间
    4. 通过ioctl, 将IPC数据传给Binder Driver, binder_ioctl()负责在两个进程收发IPC数据和IPC reply数据; binder_ioctl_write_read(), (一)先把用户空间数据copy到内核空间bwr, (二)当bwr写缓存有数据, 则执行binder_thread_write(), (三)当bwr读缓存有数据, 则执行binder_thread_read(), (四)把内核数据bwr copy到用户空间
  • BWR核心数据结构, 即binder_write_read, 包含了写缓存write_buffer和读缓存read_buffer, 包含了BR Protocol, 和binder_transaction_data[target, code, data]
    1. copy_from_user()将用户空间IPC数据copy到内核态binder_write_read结构体
    2. copy_to_user()将内核态binder_write_read结构体copy到用户空间
  • binder_node即binder实体
  • Binder通信
    1. binder_thread_write()请求码为BC_TRANSACTIONBC_REPLY -> binder_transaction()
    2. binder_thread_read()
  • Binder内存机制 虚拟用户地址空间和虚拟内核地址空间都映射到同一物理内存, 当Client与Server发送数据时, Client把数据通过IPC通信copy_from_user copy到内核空间, Server端和内核共享内存
  • BpBinder即客户端, BBinder即服务端

1.6.2 ServiceManager

  • 启动流程:
    1. 打开binder驱动: binder_open(), 系统调用open("/dev/binder", O_RDWR)打开, Binder驱动层会创建binder_proc, 通过系统调用mmap()映射binder内存
    2. 注册成为服务管家: binder_become_context_manager() -> binder_ioctl() -> binder_ioctl_set_ctx_mgr() , 创建ServiceManager实体, 即binder_node
    3. 进入循环, 等待客户端请求: binder_loop() -> binder_write()发送命令给binder驱动 -> binder_ioctl()进行binder读写操作 -> binder_ioctl_write_read() copy用户数据到bwr -> binder_thread_write()设置当前线程的looper状态为BINDER_LOOPER_STATE_ENTERED; binder_parse()
    4. 备注: ServiceManager最核心功能为查询和注册服务, 注册服务即记录服务名和handle信息, 保存到svclist列表; 查询服务即根据服务名查询相应的handle信息
  • 获取ServiceManager
    1. IServiceManager#defaultServiceManager() -> interface_cast<IServiceManager>(ProcessState::self()->getContexObject(NULL));
    2. ProcessState::self() -> getContextObject(), 用于获取BpBinder对象
    3. defaultServiceManager()等价于new BpServiceManager(new BpBinder(0))

1.6.3 注册服务(addService)

  • 流程
    1. ProcessState::self(), 打开Binder驱动, 调用mmap(), 给binder分配一块虚拟地址空间
    2. defaultServiceManager() -> defaultServiceManager() -> addService(String16("media.player"), new MediaPlayerService()) -> BpServiceManager#addService()即调用BpBinder对象的transact() -> IPCThreadState::self() ->transact(), IPCThreadState包含mInmOut用于接收和存储Binder设备的数据, 默认256字节, IPCThreadState::self() ->transact()包含以下操作
      • -> errorCheck() 数据错误检查
      • -> writeTransactionData() 传输数据, 把Binder请求码BC_TRANSACTIONbinder_transaction_data写入mOut
      • -> waitForResponse()等待响应 -> IPCThreadState#talkWithDriver() -> ioctl() -> binder_ioctl() -> binder_ioctl_write_read() , binder_ioctl_write_read()包含以下操作
        • copy_from_user(), 将用户空间数据copy到内核空间
        • binder_thread_write()将数据放入目标进程 -> binder_transaction()
        • binder_thread_read()读取自己队列的数据
    3. ProcessState::self() -> startThreadPool()启动Binder线程池
    4. IPCThreadState::self()->joinThreadPool()当前线程加入线程池

1.6.4 查询服务(getService)

  • 流程
    1. defaultServiceManager, 获取ServiceManager
    2. sm->getService(String16("media.player"));获取”media.player”服务
    3. BpServiceManager#checkService(), 检查服务是否存在
    4. BpBinder#transact() -> IPCThreadState::self()->transact()
    5. IPCThreadState:transact() 包含如下操作
      • writeTransactionData()传输数据
      • IPCThreadState#waitForResponse() -> IPCThreadState#talkWithDriver()
    6. 最终readStrongBinder(), 返回BBinder对象

1.6.5 如何使用Binder In Native

  • 服务端
sp<IServiceManager> sm = defaultServiceManager();
sm->addService("service.myservice", new BnMyService());
ProcessState::self()->startThreadPol();//启动线程池
IPCThreadState::self()->joinThreadPool();//把主线程加入线程池
  • 客户端
sp<IServiceManager> sm = defaultServiceManager();
sp<IBinder> binder = sm->getService(String16("service.myservie"));
sp<IMyService> cs = interface_cast<IMyService>(binder);
cs->sayHello();
  • 创建MyService, 定义接口, 定义BnMyService(Binder服务器)和BpMyService(Binder客户端)
  • IMyService.cpp, 实现相关接口

1.6.6 AIDL

  • 服务端
public class RemoteService extends Service {
    public IBinder onBinder(Intent intent) {
        returen mBinder;
    }
    // 实现IRemoteService定义的方法
    xxx = new IRemoteService.Stub() {
        xxx
    }
}
  • 客户端
Intent intent = new Intent(xxx, RemoteService.class);
intent.setPackage(IRemoteService.class.getName());
bindService(intent, mConnection, Context.BIND_AUTO_CREATE);

private ServiceConnection mConnection = new ServiceConnection() {
    public void onServiceConnected(ComponentName name, IBinder service) {

    }
}

服务器Client                   服务Server

业务层  IRmoteService           IRemoteService[实现]

---------------------------------------------

服务Proxy                             服务Stub

RPC层    IRemoteService.Stub.Proxy    IRemoteService.Stub

--------------------------------------------------

IPC层    BinderProxy                 Binder

-----------------------------------------