进程间通信之Binder机制浅析

本博客源码基于Android 8.0

BinderAndroid提供的一种进程间通信(IPC)机制。被广泛的应用于Android系统中,比如我们经常使用的四大组件,它们的相关操作都会通过Binder最终交于其相应的Service进行处理。本文将从Binder的架构、原理、FrameworkBinder代码等,进行分析理解Binder

什么是Binder?

  • IPC角度来说:Binder是一种Android提供的跨进程通信方式。
  • 从其根源来说:Binder可以理解为一种虚拟的物理设备,其设备驱动是/dev/binder
  • Framework层角度:BinderServiceManager连接各种Manager(ActivityManagerAlarmManager等)和相应ManagerService(ActivityManagerServiceAlarmManagerService等)的桥梁。
  • 从应用层来说: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是一个接口,此接口描述与远程处理对象进行交互的抽象协议,是高性能、轻量级远程调用机制的核心部分。其代表了一种跨进程通信的能力,只要实现它就具有跨进程通信的能力。
IBinder

transact(int, Parcel, Parcel, int)

public boolean transact(int code, @NonNull Parcel data, @Nullable Parcel reply, int flags)
        throws RemoteException;
  • code:代表要执行操作的代码。其取值范围在FIRST_CALL_TRANSACTIONLAST_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代理对象。下面我们通过源码来对比BinderBinderProxy

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;
}

根据上面的代码,可以清楚的发现BinderBinderProxy的区别,我们还可以发现它们都使用了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类发现,会将一个IInterfaceBinder本地对象绑定,asBinder()将会返回当前绑定Binder的代理对象。IInterfaceServer端实现,Client端调用接口方法,也就是说Server端接触的是Binder本地对象,Client端所接触的是ServerBinder对象的代理对象。

在这里我并没有分析到ServiceManager相关内容,这些将放到后面的文章。

小结Binder工作原理

下面给出一张图轻松理解它们的工作原理:
图片来自Carson_Ho
图片来自Carson_Ho 点击查看

一图理解Binder架构

图片来源自Gityuan

在学习Binder过程中,发现来自Gityuan的Binder系列博文,其 Binder系列7—framework层分析 博文中提供的这张图,简单明了的阐述了Binder的架构。

Binder采用 C/S 架构,主要包含ClientServerServiceManagerBinder驱动。其中ServiceManager用于管理系统中各种Service

Framework层通过JNI方式和Native层进行交互,Native层通过ioctl方式和Kernel层的Binder驱动进行通信。

总结

Binder机制设计层面很广,贯穿了整个Android系统,从Framework层一直到Kernel层。本文只是对Framework做相应的浅析,对整个Binder机制的分析可以参考文末提供的资源链接进一步学习。

接下来我会对AIDL进行解析,然后再解析ServiceManager。因为各种ManagerService都是有AIDL实现,然后交由ServiceManager进行管理,这样更能加深对Framework层相关内容的理解。

Thanks

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值