Android Binder

来源:互联网 发布:通往天堂的钥匙淘宝网 编辑:程序博客网 时间:2024/06/07 11:59

1.Binder实例

 

Step-1. Activity使用startService()函數來啟動Service

Step-2. Activity調用bindService()来绑定Service。亦即,Activity建立与Service之间的连结(Connection)

Step-3. Activity調用IBinder接口的transact()函数,透过底层Binder Driver驱动而间接調用到Binder基类的execTransact()函数,转而調用 myBinderonTransact()函数。

 

package com.example.test2; import android.app.Activity;import android.content.ComponentName;import android.content.Context;import android.content.Intent;import android.content.ServiceConnection;import android.os.Bundle;import android.os.IBinder;import android.os.Parcel;import android.util.Log; public class MainActivity extends Activity { private Mp3Binder mp3bind;private ServiceConnection mConnection =new ServiceConnection() {public void onServiceConnected(ComponentName className, IBinder ibinder) {Log.e("MainActivity", "----------");mp3bind = (Mp3Binder)ibinder;Log.e("MainActivity", "+++++++++++");if(mp3bind == null){Log.e("MainActivity", "pProxy null");}else{Log.e("MainActivity", "pProxy notnull");Parcel data = Parcel.obtain();Parcel reply = Parcel.obtain();data.writeString("playing");try{mp3bind.transact(1, data, reply, 0);//mStatus = reply.readString();System.out.println("---"+reply.readString());}catch (Exception e){e.printStackTrace();}}Log.e("MainActivity", "pProxy aaaa");} @Overridepublic void onServiceDisconnected(ComponentName name){// TODO 自动生成的方法存根Log.e("MainActivity", "pProxy bbbb");}};    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);         startService(new Intent("com.example.test2.REMOTE_SERVICE"));                bindService(new Intent("com.example.test2.REMOTE_SERVICE"),         mConnection, Context.BIND_AUTO_CREATE);    }}


 

package com.example.test2; import android.content.Context;import android.media.MediaPlayer;import android.os.Binder;import android.os.Message;import android.os.Parcel;import android.util.Log; /** * 实现具体方法 * @author chenhan * */public class Mp3Binder extends Binder{private Context ctx;public Mp3Binder(Context cx){ctx= cx;}@Overridepublic boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws android.os.RemoteException{reply.writeString(data.readString()+ " mp3");//Log.e("mp3Binder", data.readString());if(code == 1){Log.e("mp3Binder", "mp3Binder : play");}else if(code == 2){Log.e("mp3Binder", "mp3Binder : stop");}return true;}}

 

package com.example.test2; import android.app.Service;import android.content.Intent;import android.os.IBinder;import android.util.Log; public class Mp3RemoteService extends Service {private IBinder mBinder = null;@Overridepublic void onCreate(){Log.e("mp3RemoteService", "mp3RemoteService : start");mBinder = new Mp3Binder(getApplicationContext());Log.e("mp3RemoteService", "mp3RemoteService : over");}@Overridepublic IBinder onBind(Intent intent){return mBinder;}}

 

2.Binder原理

所谓建好了服务绑定(Bind)之后,就如同建好了跨进程的桥梁。之后,就能随时透过这桥梁而进行从myActivity調用到myService的跨进程IPC通信。绑定了服务之后,就能从myActivity調用BinderProxy(透过IBinder接口)IBinder接口,执行了transact()函数。如下图:

 

在上图里,从JNI本地模块拉了一条红色虚线,表示这并非直接的通信途径。也就是,实际上是透过底层Binder Driver驱动才調用到BBinderIBinder接口。如下图:

 

 

3.Binder通信

Binder是一种基于C/S架构,主要包括四个部分:服务端(Server),客户端(Client)Binder驱动,ServiceManagerBinderAndroid系统中非常重要的一种IPC机制,如果你想研究Frameworks,必须先对Binder机制诱有一定的认识,否则是无法看懂Frameworks源码的。上述四个部分分别在不同的进程中,他们之间的交互都是通过Binder实现,现在站在宏观的角度来分析Server,Client,ServiceManager之间的关系,如下图:

 

 

Android需要建立一套新的IPC机制来满足系统对通信方式,传输性能和安全性的要求,这就是BinderBinder基于 Client-Server通信模式,传输过程只需一次拷贝,为发送发添加UID/PID身份,既支持实名Binder也支持匿名Binder,安全性 高。

 

 

 

所谓将数据从进程A传递到进程B,就是将进程A的某块用户空间(0~3G)的内容复制到进程B的某块用户空间(0~3G)的内存中。

因此,为了将数据从一个进程A复制到另一个进程B,我们需要:

1. 切换到内核态。因为只有内核态才能访问所有进程的用户态空间。

2. 将数据从进程A的用户态空间读出。

3. 在进程B的用户态空间中找一块内存空间,为其分配物理内存,然后将数据复制到该物理内存处。

4. 然后,进程B就可以从其用户空间读到数据了。

 

Binder Driver是如何在进程间传递数据的其实,Binder driver要做的事情就是上面我们所列出的那几个步骤。

不过,对于每个进程,Binder driver会在进程打开binder driver后,通过ioctl系统调用为每个进程预先找一块用户态和内核态的内存空间,做为Binder buffer使用。

请注意,对于一个进程而言,其Binder buffer在用户态和内核态的内存被映射到了同样的物理内存地址。

 

下面我们看看利用Binder进行通信的两个进程之间是如何传递数据的:

1. Client进程有一块内存内容需要传递给Server进程

2. 切换到内核态

3. Binder driverClient进程的用户态空间(0~3G)的这块内存内容

4. Binder driver将读出的内容复制到Server进程的Binder buffer

5. 然后,当Server进程执行时,就能够在其用户态空间(0~3G)读传过来的内容了。因为Binder Buffer也被映射到了Server进程的用户态空间。

6. Server进程处理完读出的消息后,然后需要将处理的结果存放在一块用户态空间的内存中,希望将其返回给Client进程

7. 切换到内核态

8. Binder driverServer进程的用户态空间(0~3G)的处理结果

4. Binder driver将读出的内容复制到Client进程的Binder buffer

5. 然后,当Client进程执行时,就能够在其用户态空间(0~3G)读传过来的内容了。因为Binder Buffer也被映射到了Client进程的用户态空间。

这就是Binder driver如何实现进程间通信的。

 

原创粉丝点击