Binder 通信流程

2016-5-21 chenhui Binder

Binder 的一次完整通信可以看成两次或四次通讯。

  1. 第一次是 Client 发送数据给 Binder,告知 Binder 该怎么做
  2. 第二次是 Binder 发现 Client 要转发数据给别人,于是他把数据发送给对端,并返回 Client 完成信息
  3. 第三、四次是 Client 在需要返回值时,对端返回数据给 Binder,再返回给 Client


下面是步骤拆解:


第一次通信开始

  1. 第一步、得到或创建 SM 的代理对象,这样才能和 SM 通信。
  2. 第二步、Client 把数据封装到 Parcel 对象内,并和 Parcel 对象和 binder_transaction_data 对象进行关联,然后把 BTD 对象写到输出缓冲区。再把 BTD 在输出缓冲区内的开始地址和大小封装到 binder_write_read 内,使用 ioctl 把 BC_TRANSACTION 命令和 BWR 发送给 Binder 驱动。

第二次通信开始:
  1. 第三步、Binder 驱动从用户空间读入 BWR 对象,并把 BWR 的行为(读or写)交给 Client 线程池中的一个线程进行操作。对于写,他会从用户空间读出 BC_TRANSACTION  命令和 BTD 对象,根据命令的含义,他从 BTD 对象中读出对端(Service)信息,得到对端的引用对象。根据对端的引用对象,得到其实体对象,并从其线程池中找出合适线程来处理这次消息。根据 BTD 对象把数据从用户空间的 Parcel 对象中读到 binder_transtion 对象内,最后 BT 对象会被插入线程的工作队列,并唤醒该线程来处理这个 BT 对象。最后,构造一个 binder_work 给源线程(当前线程自身),表示数据已发送。当前线程处理到这个消息时,就会把 BR_TRANSACTION_COMPLETE 写回用户空间,最终进程会根据是否需要接收返回值来决定是否需要再进行一次第三步,只不过这一次是 BWR 行为是读,读的就是返回值。
  2. 第四步、对端线程被唤醒后,创建一个 BTD 对象,并读出 binder_transtion 对象,把 BT 对象中的数据信息保存到 BTD 对象中,最后把 BTD 对象写到用户空间的输入缓冲区,最终在用户空间解析数据并进行处理,具体怎么处理,不同的 Service 都不一样。总之,一次数据通信就完成了。

第三、四次数据通信开始(需要返回值),基本步骤和前两次是一样的。
  1. 第五步、对端在用户空间处理完数据后,和第一步一样,也构造一个保存了返回数据的 BWR 及相关对象调用 ioctl 来通知 Binder 驱动,不同的是 Binder 命令从 BC_TRANSACTION 变成了 BC_REPLY。
  2. 第六步、基本和第二步一样,得到 Client 的实体对象,把数据封装成 BT 对象,交给线程池中的一个线程。Client 线程得到该 BT 对象后,创建一个 BTD 对象来关联 BT 对象内的数据,并把他和一个 BR_REPLY 命令写回到用户空间,最终用户空间处理。数据通信彻底完成。



发表评论:

Copyright ©2015-2016 freehui All rights reserved