老罗的ANDROID之旅---IPC学习笔记
2013-10-11 10:10
471 查看
下面所涉及到的内容基本上都来自---老罗的Android之旅
在Android系统的Binder机制中,由一系统组件组成,分别是Client、Server、Service Manager和Binder驱动程序,其中Client、Server和Service Manager运行在用户空间,Binder驱动程序运行内核空间。Binder就是一种把这四个组件粘合在一起的粘结剂了,其中,核心组件便是Binder驱动程序了,Service
Manager提供了辅助管理的功能,Client和Server正是在Binder驱动和Service Manager提供的基础设施上,进行Client-Server之间的通信。Service Manager和Binder驱动已经在Android平台中实现好,开发者只要按照规范实现自己的Client和Server组件就可以了。说起来简单,做起难,对初学者来说,Android系统的Binder机制是最难理解的了,而Binder机制无论从系统开发还是应用开发的角度来看,都是Android系统中最重要的组成,因此,很有必要深入了解Binder的工作方式。
Android系统Binder机制中的四个组件Client、Server、Service Manager和Binder驱动程序的关系如下图所示:
说明;
1. Client、Server和Service Manager实现在用户空间中,Binder驱动程序实现在内核空间中
2. Binder驱动程序和Service Manager在Android平台中已经实现,开发者只需要在用户空间实现自己的Client和Server
3. Binder驱动程序提供设备文件/dev/binder与用户空间交互,Client、Server和Service Manager通过open和ioctl文件操作函数与Binder驱动程序进行通信
4. Client和Server之间的进程间通信通过Binder驱动程序间接实现
5. Service Manager是一个守护进程,用来管理Server,并向Client提供查询Server接口的能力
接下来我们通过以下几个情景来进一步对Binder源码进行分析,深入了解Binder机制
一:浅谈Service
实在是太复杂,涉及的数据结构特别多,要理解好必须得对Linux内核,驱动等要好好掌握。。。。
下面用一时序图进行简要的梳理一下相关的流程。
总结一下,Service Manager是成为Android进程间通信(IPC)机制Binder守护进程的过程是这样的:
1. 打开/dev/binder文件:open("/dev/binder", O_RDWR);
2. 建立128K内存映射:mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, bs->fd, 0);
3. 通知Binder驱动程序它是守护进程:binder_become_context_manager(bs);
4. 进入循环等待请求的到来:binder_loop(bs, svcmgr_handler);
在这个过程中,在Binder驱动程序中建立了一个struct binder_proc结构、一个struct binder_thread结构和一个struct binder_node结构,这样,Service Manager就在Android系统的进程间通信机制Binder担负起守护进程的职责了。
二:浅谈Android系统进程间通信(IPC)机制Binder中的Server和Client获得Service
上面介绍了Service
Manager是如何成为Binder机制的守护进程的。既然作为守护进程,Service Manager的职责当然就是为Server和Client服务了。那么,Server和Client如何获得Service Manager接口,进而享受它提供的服务呢?下面将简要分析Server和Client获得Service Manager的过程。
首先上一相关类图
说明:其中BpInterface是一个模板类,IServiceManager类继承了IInterface类,而IInterface类和BpRefBase类又分别继承了RefBase类。在BpRefBase类中,有一个成员变量mRemote,它的类型是IBinder*,实现类为BpBinder,它表示一个Binder引用,引用句柄值保存在BpBinder类的mHandle成员变量中。BpBinder类通过IPCThreadState类来和Binder驱动程序并互,而IPCThreadState又通过它的成员变量mProcess来打开/dev/binder设备文件,mProcess成员变量的类型为ProcessState。ProcessState类打开设备/dev/binder之后,将打开文件描述符保存在mDriverFD成员变量中,以供后续使用。
在了解了相关类之间的关系之后,我们从defaultServiceManager()开始进行代码的跟中,下面是其相关时序图:
也就是说在defaultServiceManager()中:最终的gDefaultServiceManager
= new BpServiceManager(new BpBinder(0)。
这样,Service
Manager远程接口就创建完成了,它本质上是一个BpServiceManager,包含了一个句柄值为0的Binder引用。
在Android系统的Binder机制中,Server和Client拿到这个Service Manager远程接口之后怎么用呢?
对Server来说,就是调用IServiceManager::addService这个接口来和Binder驱动程序交互了,即调用BpServiceManager::addService 。而BpServiceManager::addService又会调用通过其基类BpRefBase的成员函数remote获得原先创建的BpBinder实例,接着调用BpBinder::transact成员函数。在BpBinder::transact函数中,又会调用IPCThreadState::transact成员函数,这里就是最终与Binder驱动程序交互的地方了。回忆一下前面的类图,IPCThreadState有一个PorcessState类型的成中变量mProcess,而mProcess有一个成员变量mDriverFD,它是设备文件/dev/binder的打开文件描述符,因此,IPCThreadState就相当于间接在拥有了设备文件/dev/binder的打开文件描述符,于是,便可以与Binder驱动程序交互了。
对Client来说,就是调用IServiceManager::getService这个接口来和Binder驱动程序交互了。具体过程上述Server使用Service Manager的方法是一样的。
下面就深入到Binder驱动程序这一层,进行详细的源代码分析,以便更好地理解Binder进程间通信机制。
在IServiceManager::addService过程中。对IServiceManager::addService过程中MediaPlayerService、ServiceManager和BinderDriver之间的交互不是很了解,附上老罗的一张它们三者之间的交互图
至此,Server就启动起来了,Server启动起来之后,就会在一个无穷循环中等待Client的请求了,下面我们将介绍Client如何通过Service
Manager远程接口来获得Server远程接口,进而调用Server远程接口来使用Server提供的服务
以上3、4的说明(来自评论)
首先server和client都调用了ProcessState的构造函数从而都向驱动申请了一块物理内存用于通信数据的存放,然后:
1.server调用SM的addService函数传递一个字符串和实际Binder对象在自己虚拟地址空间的地址到Binder驱动,Binder驱动记录下该地址值,在SM申请的物理内存中分配一个虚拟地址并连同字符串一起传递给SM,而且Binder驱动会记录下两个地址之间的对应关系.
2.client调用SM的getService函数传递一个字符串给SM,SM将相对应的虚拟地址值传递给Binder驱动,Binder驱动查询出实际对象的地址,在client申请的物理内存中分配一个虚拟地址并传递给client,而且Binder驱动会记录下这个地址和实际Binder对象地址之间的对应关系,client这里得到的就是实际Binder的引用了.
到了这一步,真正的Binder对象就拥有两个引用,一个在SM,一个client.
3.client通过得到的Binder引用调用server中的函数,驱动会根据传递过来引用值找到应该处理该请求的进程,并唤醒其中的Binder线程,调用BBinder对象的onTransaction函数,最终调用到实际的函数。
呵呵,胡乱瞎凑完了。。。。
----------------------------------------------------谢谢 老罗的Android之旅-------------------------------------------------------------------
在Android系统的Binder机制中,由一系统组件组成,分别是Client、Server、Service Manager和Binder驱动程序,其中Client、Server和Service Manager运行在用户空间,Binder驱动程序运行内核空间。Binder就是一种把这四个组件粘合在一起的粘结剂了,其中,核心组件便是Binder驱动程序了,Service
Manager提供了辅助管理的功能,Client和Server正是在Binder驱动和Service Manager提供的基础设施上,进行Client-Server之间的通信。Service Manager和Binder驱动已经在Android平台中实现好,开发者只要按照规范实现自己的Client和Server组件就可以了。说起来简单,做起难,对初学者来说,Android系统的Binder机制是最难理解的了,而Binder机制无论从系统开发还是应用开发的角度来看,都是Android系统中最重要的组成,因此,很有必要深入了解Binder的工作方式。
Android系统Binder机制中的四个组件Client、Server、Service Manager和Binder驱动程序的关系如下图所示:
说明;
1. Client、Server和Service Manager实现在用户空间中,Binder驱动程序实现在内核空间中
2. Binder驱动程序和Service Manager在Android平台中已经实现,开发者只需要在用户空间实现自己的Client和Server
3. Binder驱动程序提供设备文件/dev/binder与用户空间交互,Client、Server和Service Manager通过open和ioctl文件操作函数与Binder驱动程序进行通信
4. Client和Server之间的进程间通信通过Binder驱动程序间接实现
5. Service Manager是一个守护进程,用来管理Server,并向Client提供查询Server接口的能力
接下来我们通过以下几个情景来进一步对Binder源码进行分析,深入了解Binder机制
一:浅谈Service
Manager成为Android进程间通信(IPC)机制Binder守护进程之路
实在是太复杂,涉及的数据结构特别多,要理解好必须得对Linux内核,驱动等要好好掌握。。。。下面用一时序图进行简要的梳理一下相关的流程。
总结一下,Service Manager是成为Android进程间通信(IPC)机制Binder守护进程的过程是这样的:
1. 打开/dev/binder文件:open("/dev/binder", O_RDWR);
2. 建立128K内存映射:mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, bs->fd, 0);
3. 通知Binder驱动程序它是守护进程:binder_become_context_manager(bs);
4. 进入循环等待请求的到来:binder_loop(bs, svcmgr_handler);
在这个过程中,在Binder驱动程序中建立了一个struct binder_proc结构、一个struct binder_thread结构和一个struct binder_node结构,这样,Service Manager就在Android系统的进程间通信机制Binder担负起守护进程的职责了。
二:浅谈Android系统进程间通信(IPC)机制Binder中的Server和Client获得Service
Manager接口之路
上面介绍了ServiceManager是如何成为Binder机制的守护进程的。既然作为守护进程,Service Manager的职责当然就是为Server和Client服务了。那么,Server和Client如何获得Service Manager接口,进而享受它提供的服务呢?下面将简要分析Server和Client获得Service Manager的过程。
首先上一相关类图
说明:其中BpInterface是一个模板类,IServiceManager类继承了IInterface类,而IInterface类和BpRefBase类又分别继承了RefBase类。在BpRefBase类中,有一个成员变量mRemote,它的类型是IBinder*,实现类为BpBinder,它表示一个Binder引用,引用句柄值保存在BpBinder类的mHandle成员变量中。BpBinder类通过IPCThreadState类来和Binder驱动程序并互,而IPCThreadState又通过它的成员变量mProcess来打开/dev/binder设备文件,mProcess成员变量的类型为ProcessState。ProcessState类打开设备/dev/binder之后,将打开文件描述符保存在mDriverFD成员变量中,以供后续使用。
在了解了相关类之间的关系之后,我们从defaultServiceManager()开始进行代码的跟中,下面是其相关时序图:
也就是说在defaultServiceManager()中:最终的gDefaultServiceManager
= new BpServiceManager(new BpBinder(0)。
这样,Service
Manager远程接口就创建完成了,它本质上是一个BpServiceManager,包含了一个句柄值为0的Binder引用。
在Android系统的Binder机制中,Server和Client拿到这个Service Manager远程接口之后怎么用呢?
对Server来说,就是调用IServiceManager::addService这个接口来和Binder驱动程序交互了,即调用BpServiceManager::addService 。而BpServiceManager::addService又会调用通过其基类BpRefBase的成员函数remote获得原先创建的BpBinder实例,接着调用BpBinder::transact成员函数。在BpBinder::transact函数中,又会调用IPCThreadState::transact成员函数,这里就是最终与Binder驱动程序交互的地方了。回忆一下前面的类图,IPCThreadState有一个PorcessState类型的成中变量mProcess,而mProcess有一个成员变量mDriverFD,它是设备文件/dev/binder的打开文件描述符,因此,IPCThreadState就相当于间接在拥有了设备文件/dev/binder的打开文件描述符,于是,便可以与Binder驱动程序交互了。
对Client来说,就是调用IServiceManager::getService这个接口来和Binder驱动程序交互了。具体过程上述Server使用Service Manager的方法是一样的。
下面就深入到Binder驱动程序这一层,进行详细的源代码分析,以便更好地理解Binder进程间通信机制。
三:Android系统进程间通信(IPC)机制Binder中的Server启动过程源代码分析
以MediaPlayerService为例,看其Server的启动过程:在IServiceManager::addService过程中。对IServiceManager::addService过程中MediaPlayerService、ServiceManager和BinderDriver之间的交互不是很了解,附上老罗的一张它们三者之间的交互图
至此,Server就启动起来了,Server启动起来之后,就会在一个无穷循环中等待Client的请求了,下面我们将介绍Client如何通过Service
Manager远程接口来获得Server远程接口,进而调用Server远程接口来使用Server提供的服务
四:Android系统进程间通信(IPC)机制Binder中的Client获得Server远程接口过程源代码分析
以Android系统中自带的多媒体播放器为例子来说明Client是如何通过IServiceManager::getService接口来获得MediaPlayerService这个Server的远程接口的:下面是相关序列图以上3、4的说明(来自评论)
首先server和client都调用了ProcessState的构造函数从而都向驱动申请了一块物理内存用于通信数据的存放,然后:
1.server调用SM的addService函数传递一个字符串和实际Binder对象在自己虚拟地址空间的地址到Binder驱动,Binder驱动记录下该地址值,在SM申请的物理内存中分配一个虚拟地址并连同字符串一起传递给SM,而且Binder驱动会记录下两个地址之间的对应关系.
2.client调用SM的getService函数传递一个字符串给SM,SM将相对应的虚拟地址值传递给Binder驱动,Binder驱动查询出实际对象的地址,在client申请的物理内存中分配一个虚拟地址并传递给client,而且Binder驱动会记录下这个地址和实际Binder对象地址之间的对应关系,client这里得到的就是实际Binder的引用了.
到了这一步,真正的Binder对象就拥有两个引用,一个在SM,一个client.
3.client通过得到的Binder引用调用server中的函数,驱动会根据传递过来引用值找到应该处理该请求的进程,并唤醒其中的Binder线程,调用BBinder对象的onTransaction函数,最终调用到实际的函数。
5、Android系统进程间通信Binder机制在应用程序框架层的Java接口源代码分析
package android.os; interface IHelloService { void setVal(int val); int getVal(); } public interface IHelloService extends android.os.IInterface { public void setVal(int val) throws android.os.RemoteException; public int getVal() throws android.os.RemoteException; public static abstract class Stub extends android.os.Binder implements android.os.IHelloService { static final int TRANSACTION_setVal = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0); static final int TRANSACTION_getVal = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1); public Stub(){} public static android.os.IHelloService asInterface(android.os.IBinder obj){ ... return new android.os.IHelloService.Stub.Proxy(obj); } public android.os.IBinder asBinder(){} public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException { ... case TRANSACTION_setVal: ... case TRANSACTION_getVal: ... } private static class Proxy implements android.os.IHelloService { private android.os.IBinder mRemote; Proxy(android.os.IBinder remote) {} public android.os.IBinder asBinder() {} public java.lang.String getInterfaceDescriptor() {} public void setVal(int val) throws android.os.RemoteException { ... mRemote.transact(Stub.TRANSACTION_setVal, _data, _reply, 0); ... } public int getVal() throws android.os.RemoteException { ... mRemote.transact(Stub.TRANSACTION_getVal, _data, _reply, 0); ... } } } } 这里我们可以看到IHelloService.aidl这个文件编译后的真面目,原来就是根据IHelloService接口的 定义生成相应的Stub和Proxy类,这个就是我们熟悉的Binder机制的内容了,即实现这个HelloService 的Server必须继续于这里的IHelloService.Stub类,而这个HelloService的远程接口就是这里的 IHelloService.Stub.Proxy对象获得的IHelloService接口 public class HelloService extends IHelloService.Stub { private static final String TAG = "HelloService"; HelloService() { init_native(); } public void setVal(int val) { setVal_native(val); } public int getVal() { return getVal_native(); } private static native boolean init_native(); private static native void setVal_native(int val); private static native int getVal_native(); } 有了HelloService这个Server类后,下一步就是考虑怎么样把它启动起来了。 在frameworks/base/services/java/com/android/server/SystemServer.java文件中,定义了SystemServer类。 SystemServer对象是在系统启动的时候创建的,它被创建的时候会启动一个线程来创建HelloService,并且把它 添加到Service Manager中去。 class ServerThread extends Thread { ...... @Override public void run() { ...... Looper.prepare(); ...... try { Slog.i(TAG, "Hello Service"); ServiceManager.addService("hello", new HelloService()); //ServiceManagerProxy.addService() } catch (Throwable e) { Slog.e(TAG, "Failure starting Hello Service", e); } ...... Looper.loop(); ...... } } ...... public class SystemServer { native public static void init1(String[] args); ...... public static final void init2() { Slog.i(TAG, "Entered the Android system server!"); Thread thr = new ServerThread(); thr.setName("android.server.ServerThread"); thr.start(); } ...... } 而Client端就是借助Service Manager这个Java远程接口来获得HelloService的远程接口的: public class Hello extends Activity implements OnClickListener { ...... private IHelloService helloService = null; ...... @Override public void onCreate(Bundle savedInstanceState) { helloService = IHelloService.Stub.asInterface(ServiceManager.getService("hello")); //====》 //helloService = IHelloService.Stub.asInterface(ServiceManagerProxy.getService("hello")); //====》 //helloService = IHelloService.Stub.asInterface(new BinderProxy())); //====>> //helloService = android.os.IHelloService.Stub.Proxy(new BinderProxy()); } ...... } 这样,我们就获得了HelloService的远程接口了,它实质上是一个实现了IHelloService接口的IHelloService.Stub.Proxy对象。 然后通过client端的helloService.getVal以及setVal来调用android.os.IHelloService.Stub.Proxy的setVal、getVal进而调用 mRemote.transact来请求HelloService执行TRANSACTION_getVal操作。经过一大圈又回到android.os.IHelloService.Stub的onTransact 来执行相关的调用......函数最终又调用了HelloService.getVal函数,最终,经过层层返回,就回到IHelloService.Stub.Proxy.getVal函数中来
呵呵,胡乱瞎凑完了。。。。
----------------------------------------------------谢谢 老罗的Android之旅-------------------------------------------------------------------
相关文章推荐
- 老罗android之旅补丁版之四JNI
- 在Ubuntu上为Android系统内置C可执行程序测试Linux内核驱动程序 (学习老罗的)
- 在Ubuntu上为Android增加硬件抽象层(HAL)模块访问Linux内核驱动程序 (学习老罗的)
- 老罗将死,或者Android也将就换代,但是互联网的,共享,互助精神将永存
- 老罗Android开发视频
- 那两年炼就的Android内功修养(转载老罗的)
- csdn 134 老罗 android
- 老罗:Android视图SurfaceView的实现原理分析
- 老罗Android视频[详细版]全集下载(含源码)
- 老罗的blog-------------android 相关blog
- 在A20上演示老罗的Android硬件抽象层(HAL)概要介绍和学习计划2--关于kernel部分
- 老罗android之旅学习
- 那两年炼就的Android内功修养 ( 老罗 )
- 老罗:Android系统中的广播(Broadcast)机制简要介绍和学习计划
- 老罗android开发视频教程学习完了
- 老罗的Android之旅--网址
- 读老罗android总结
- 老罗的Android之旅 (《Android系统源代码情景分析》)
- 那两年炼就的Android内功修养 ( 老罗 )
- 老罗的ANDROID之旅---硬件抽象层学习笔记