欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

进程间通信之Binder机制浅析

程序员文章站 2024-02-11 21:20:46
...

本博客源码基于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是一个接口,此接口描述与远程处理对象进行交互的抽象协议,是高性能、轻量级远程调用机制的核心部分。其代表了一种跨进程通信的能力,只要实现它就具有跨进程通信的能力。
进程间通信之Binder机制浅析

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工作原理

下面给出一张图轻松理解它们的工作原理:
进程间通信之Binder机制浅析
图片来自Carson_Ho 点击查看

一图理解Binder架构

进程间通信之Binder机制浅析

在学习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

相关标签: Binder机制