进程间通信之Binder机制浅析
本博客源码基于Android 8.0
Binder
,Android
提供的一种进程间通信(IPC)机制。被广泛的应用于Android
系统中,比如我们经常使用的四大组件,它们的相关操作都会通过Binder
最终交于其相应的Service
进行处理。本文将从Binder
的架构、原理、Framework
层Binder
代码等,进行分析理解Binder
。
什么是Binder?
- 从
IPC
角度来说:Binder
是一种Android
提供的跨进程通信方式。 - 从其根源来说:
Binder
可以理解为一种虚拟的物理设备,其设备驱动是/dev/binder
。 - 从
Framework
层角度:Binder
是ServiceManager
连接各种Manager
(ActivityManager
、AlarmManager
等)和相应ManagerService
(ActivityManagerService
、AlarmManagerService
等)的桥梁。 - 从应用层来说:
Binder
是客户端和服务端通信的媒介。当bindService
时,服务端会返回一个包含了服务端业务调用的Binder
对象,通过这个Binder
对象,客户端可以获取到服务端提供的服务和数据。
Java 层 Binder 理解
framework/base/core/java/android/os/
- IBinder.java
- Binder.java
- BinderProxy.java
- IInterface.java
- ServiceManager.java
- ServiceManagerNative.java
- ServiceManagerProxy.java
IBinder
IBinder
是一个接口,此接口描述与远程处理对象进行交互的抽象协议,是高性能、轻量级远程调用机制的核心部分。其代表了一种跨进程通信的能力,只要实现它就具有跨进程通信的能力。
transact(int, Parcel, Parcel, int)
public boolean transact(int code, @NonNull Parcel data, @Nullable Parcel reply, int flags)
throws RemoteException;
-
code
:代表要执行操作的代码。其取值范围在FIRST_CALL_TRANSACTION
和LAST_CALL_TRANSACTION
之间(0x00000001~0x00ffffff)
。在IBinder
中定义好了一些操作的代码:-
PING_TRANSACTION
:表示调用pingBinder()
-
DUMP_TRANSACTION
:表示获取内部状态 -
SHELL_COMMAND_TRANSACTION
:执行一个shell
命令 -
INTERFACE_TRANSACTION
:询问事务的收件人端的规范接口描述符
-
-
data
:传入的数据 -
reply
:返回的数据 -
flags
:额外的操作标志。有两个可取值:-
0
:代表正常的远程调用过程 -
FLAG_ONEWAY
:代表单向调用, 这意味着调用方立即返回, 而不等待被调用者的结果。仅当调用方和被调用者处于不同进程时才应用。
-
getInterfaceDescriptor()
/**
* 获取当前 Binder 支持的接口的规范名称。
*/
public @Nullable String getInterfaceDescriptor() throws RemoteException;
pingBinder()
/**
* 检测远程 Binder 对象是否存在
*/
public boolean pingBinder();
isBinderAlive()
/**
* 检测 Binder 所在进程是否还存在
*/
public boolean isBinderAlive();
queryLocalInterface(String)
/**
* 尝试检索本地绑定对象实现的 IInterface 接口。
*/
public @Nullable IInterface queryLocalInterface(@NonNull String descriptor);
linkToDeath()
public interface DeathRecipient {
public void binderDied();
}
/**
* 注册一个Binder销毁监听
*/
public void linkToDeath(@NonNull DeathRecipient recipient, int flags)
throws RemoteException;
Binder和BinderProxy
Java
层的Binder
类,代表的是Binder
本地对象。BinderProxy
代表的是远程进程Binder
的代理对象。下面我们通过源码来对比Binder
和BinderProxy
:
public class Binder implements IBinder {
...
public Binder() {
mObject = getNativeBBinderHolder();
NoImagePreloadHolder.sRegistry.registerNativeAllocation(this, mObject);
...
}
/**
* 将IInterface接口实现、一个描述符和当前Binder进行绑定
*/
public void attachInterface(@Nullable IInterface owner, @Nullable String descriptor) {
mOwner = owner;
mDescriptor = descriptor;
}
...
// 返回true,只要能来到这里那么就代表着Binder还存活着
public boolean pingBinder() {
return true;
}
// 调用本地Binder,返回true,因为只要你调用它,那就证明进程还在
public boolean isBinderAlive() {
return true;
}
/**
* 根据描述符返回绑定的IInterface接口实现
*/
public @Nullable IInterface queryLocalInterface(@NonNull String descriptor) {
if (mDescriptor.equals(descriptor)) {
return mOwner;
}
return null;
}
/**
* Binder类自己的方法,实现IBinder的transact()方法具体将交由此方法执行处理
*/
protected boolean onTransact(int code, @NonNull Parcel data, @Nullable Parcel reply,
int flags) throws RemoteException {
if (code == INTERFACE_TRANSACTION) {// 获取描述符
reply.writeString(getInterfaceDescriptor());
return true;
} else if (code == DUMP_TRANSACTION) {// 获取内部信息
...
return true;
} else if (code == SHELL_COMMAND_TRANSACTION) {//执行shell命令
...
return true;
}
return false;
}
// IBinder的transact实现,最终逻辑处理交由onTransact
public final boolean transact(int code, @NonNull Parcel data, @Nullable Parcel reply,
int flags) throws RemoteException {
if (false) Log.v("Binder", "Transact: " + code + " to " + this);
if (data != null) {
data.setDataPosition(0);
}
boolean r = onTransact(code, data, reply, flags);
if (reply != null) {
reply.setDataPosition(0);
}
return r;
}
private static native long getNativeBBinderHolder();
private static native long getFinalizer();
// android_util_Binder.cpp的onTrancat的切入点
private boolean execTransact(int code, long dataObj, long replyObj,
int flags) {
...
res = onTransact(code, data, reply, flags);
...
return res;
}
}
final class BinderProxy implements IBinder {
...
private static BinderProxy getInstance(long nativeData, long iBinder) {
BinderProxy result = sProxyMap.get(iBinder);
if (result == null) {
result = new BinderProxy(nativeData);
sProxyMap.set(iBinder, result);
}
return result;
}
private BinderProxy(long nativeData) {
mNativeData = nativeData;
NoImagePreloadHolder.sRegistry.registerNativeAllocation(this, mNativeData);
}
...
public native boolean pingBinder();
public native boolean isBinderAlive();
/**
* 注意此处和Binder.java中的区别,
* BinderProxy代表的是远程进程中Binder的代理,此处返回null
*/
public IInterface queryLocalInterface(String descriptor) {
return null;
}
public boolean transact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
...
return transactNative(code, data, reply, flags);
...
}
private static native long getNativeFinalizer();
public native String getInterfaceDescriptor() throws RemoteException;
public native boolean transactNative(int code, Parcel data, Parcel reply,
int flags) throws RemoteException;
public native void linkToDeath(DeathRecipient recipient, int flags)
throws RemoteException;
public native boolean unlinkToDeath(DeathRecipient recipient, int flags);
...
/**
* C++ pointer to BinderProxyNativeData. That consists of strong pointers to the
* native IBinder object, and a DeathRecipientList.
*/
private final long mNativeData;
}
根据上面的代码,可以清楚的发现Binder
和BinderProxy
的区别,我们还可以发现它们都使用了JNI
的方式和底层进行交互。
IInterface
/**
* Base class for Binder interfaces. When defining a new interface,
* you must derive it from IInterface.
*/
public interface IInterface
{
/**
* Retrieve the Binder object associated with this interface.
* You must use this instead of a plain cast, so that proxy objects
* can return the correct result.
*/
public IBinder asBinder();
}
在解析Binder
类发现,会将一个IInterface
和Binder
本地对象绑定,asBinder()
将会返回当前绑定Binder
的代理对象。IInterface
由Server
端实现,Client
端调用接口方法,也就是说Server
端接触的是Binder
本地对象,Client
端所接触的是Server
端Binder
对象的代理对象。
在这里我并没有分析到ServiceManager
相关内容,这些将放到后面的文章。
小结Binder工作原理
下面给出一张图轻松理解它们的工作原理:
图片来自Carson_Ho 点击查看
一图理解Binder架构
在学习Binder
过程中,发现来自Gityuan
的Binder系列博文,其 Binder系列7—framework层分析 博文中提供的这张图,简单明了的阐述了Binder
的架构。
Binder
采用 C/S 架构,主要包含Client
、Server
、ServiceManager
和Binder驱动
。其中ServiceManager
用于管理系统中各种Service
。
Framework
层通过JNI
方式和Native
层进行交互,Native
层通过ioctl
方式和Kernel
层的Binder
驱动进行通信。
总结
Binder
机制设计层面很广,贯穿了整个Android
系统,从Framework
层一直到Kernel
层。本文只是对Framework
做相应的浅析,对整个Binder
机制的分析可以参考文末提供的资源链接进一步学习。
接下来我会对AIDL
进行解析,然后再解析ServiceManager
。因为各种ManagerService
都是有AIDL
实现,然后交由ServiceManager
进行管理,这样更能加深对Framework
层相关内容的理解。