本文共 3981 字,大约阅读时间需要 13 分钟。
该小节我们开始讲解Binder在Java中的实现机制,我们先来回顾一下binder系统的运行过程。
在binder的应用程序中,他会涉及3个应用程序,如下图所示:
server: 1.通过addservice(“heelo”,xxx),添加服务。 2.驱动生成一个对应的binder_node节点,binder_node中存在两个成员,分别为ptr,cokie,对于每个服务,该值的设定都不一样,后续根据这两个值区分服务 12.接收到client数据之后,读取,解析,处理,然后分局收到的ptr,cokie调用对应函数。 service_manager: 3.驱动收到到添加服务之后会创建一个binder_ref,其中存在node与desc两个成员。node指向binder_node,desc=1表示这是第一个服务。 4.应用程序会创建一个surinfo链表,其中每个节点存在成员name与handlr,如图这里为name=“hello”,handlr为驱动中的desc 7.接收到client发送的hello,在surinfo链表中查找,可以获得对应的handle值。 8.驱动根据handlr值,找到对应的binder_ref,创建一个client的binder_ref,回复给给client client: 5.通过getservice(“hello")获得服务。 6.在驱动层hello会被发送给service_manager, 9.驱动程序接收到service_manager回复的binder_ref,其中的binder_ref.node指向server中的服务,把binder_ref.desc返回给用户空间。 10.应用程序获得desc,即一个handle。 11.使用服务:首先构造数据,然后向handlr=1发送数据,驱动程序根据handlr=1找到binder_ref,根据binder_ref.proc找到server,然后发送数据给对应的server。
从上面可以看出,binder系统是非常的复杂的,所以会分成好几个层次,比如写应用程序的人,其只要写出应用程序就可以了,对于进程之间的通信,由binder驱动的系统工程师编写,现在我们讲解bander系统的分成。
其可以分为3个层次如下图:
我们打开之前边写的C++程序,test_client.cpp。可以看到:
int main(int argc, char **argv) sm->getService(String16("goodbye")); service->saygoodbye();
其并不关心内部是如何实现的,负责调用即可。函数的实现是在BnHelloService.cpp中。那么client怎么调用server中对应的函数呢?是通过第二层的RPC。
实现RPC的文件为BpGoodbyeService.cpp,其中实现了sayhello与sayhello_to两个函数。其主要是构造数据发送数据,打开BpGoodbyeService.cpp:
void saygoodbye(void) { /* 构造/发送数据 */ Parcel data, reply; data.writeInt32(0); remote()->transact(GOODBYE_SVR_CMD_SAYGOODBYE, data, &reply); } int saygoodbye_to(const char *name) { /* 构造/发送数据 */ Parcel data, reply; data.writeInt32(0); data.writeString16(String16(name)); remote()->transact(GOODBYE_SVR_CMD_SAYGOODBYE_TO, data, &reply); return reply.readInt32(); }
其工作很简单,就是构造数据之后,通过remote()->transact函数发送数据。最终导致BnHelloService.cpp中对应的onTransact被调用,然后解析再区分调用的对应的函数。
其remote()->transact如何发送数据,BnHelloService如何接受数据,怎么调用到服务的onTransact函数?
我们知道remote()得到一个Bpbinder对象,我们进入Bpbinder.cpp找到transact函数:status_t BpBinder::transact( status_t status = IPCThreadState::self()->transact(mHandle, code, data, reply, flags);
我们在看看test_server.cpp:
int main(void) /* 循环体 */ IPCThreadState::self()->joinThreadPool();
这个循环一直等待接受数据。
使用c++实现一个服务,除了IPC层不需要编写,其他的都需要我们编写。如果我们使用java编写,则只需要实现服务层即可。
打开我们之前编写的java程序,TestClient.java:
public static void main(String args[]) IBinder binder = ServiceManager.getService("hello"); IHelloService svr = IHelloService.Stub.asInterface(binder); svr.sayhello();
可以知道TestClient只需要获取服务,然后调用即可。
其具体实现为HelloService.java:public class HelloService extends IHelloService.Stub { public void sayhello() throws android.os.RemoteException { public int sayhello_to(java.lang.String name) throws android.os.RemoteException {
看起来我们似乎直接通过客户端调用服务端的函数。其实他们是用过RPC层实现的,其为IHelloService.java,该为自动生成文件。其中:
public interface IHelloService extends android.os.IInterface public static abstract class Stub extends android.os.Binder implements IHelloService public Stub()android.os.RemoteException; public static IHelloService asInterface(android.os.IBinder obj) @Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException @Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException private static class Proxy implements IHelloService @Override public void sayhello() throws android.os.RemoteException mRemote.transact(Stub.TRANSACTION_sayhello, _data, _reply, 0); @Override public int sayhello_to(java.lang.String name) throws android.os.RemoteException mRemote.transact(Stub.TRANSACTION_sayhello_to, _data, _reply, 0); public void sayhello() throws android.os.RemoteException; public int sayhello_to(java.lang.String name) throws
其上发送数据是类Proxy,接收数据的函数是onTransact。onTransact中会分别去调用的具体函数。
转载地址:http://pligz.baihongyu.com/