【Android安全】Binder解析

参考:https://zhuanlan.zhihu.com/p/35519585

关于Binder很好的介绍

https://a284628487.github.io/2018/03/04/Android-Binder/
https://mr-cao.gitbooks.io/android/content/android-binder.html

Binder一次copy的原理

在这里插入图片描述

图片名称

相比于其他IPC机制

相比于其他IPC机制(Socket、共享内存):
相比于Socket(以及管道、信号量等),Binder少了一个copy(少了copy_to_user),因此更快
相比于共享内存,无需实现复杂的访问控制策略(锁)

在这里插入图片描述

Binder代理机制

当 A 进程想要获取 B 进程中的 object 时,驱动并不会真的把 object 返回给 A,而是返回了一个跟 object 看起来一模一样的代理对象Proxy,这个 Proxy 具有和 object 一摸一样的方法,但是这些方法并没有 B 进程中 object 对象那些方法的能力,这些方法只需要把把请求参数交给驱动即可。对于 A 进程(client)来说和直接调用 object 中的方法是一样的。

当 Binder 驱动接收到 A 进程的消息后,发现这是个 Proxy 就去查询自己维护的表单,一查发现这是 B 进程 object 的代理对象。于是就会去通知 B 进程调用 object 的方法,并要求 B 进程把返回结果发给自己。当驱动拿到 B 进程的返回结果后就会转发给 A 进程,一次通信就完成了。
在这里插入图片描述

Java层Binder的各个类和接口

  • IBinder : 是一个接口。只要类实现了这个接口,类的对象就能跨进程传输。下文简称IBinder接口的实现类的对象 为 IBinder对象
    客户端调用bindService方法,接收服务端传递来的IBinder对象,存为IBinder对象serviceConnection

    intent.setAction("com.baronzhang.ipc.server");
    bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);
    
  • IInterface : 是一个接口,代表Server 提供给Client的方法的集合

  • Binder : 一个类,实现了 IBinder 接口,Binder类对象应该出现在Server端

  • BookManager:Server端定义的接口,继承IInterface接口;定义Server端提供的功能,但不实现功能
    其中功能方法的实现,在Server端新建的Stub对象中

  • Stub:AIDL生成的类,实现BookManager接口,继承Binder类

    客户端和服务端均可调用Stub类的方法

    Server端 在新建的Stub对象中,实现提供给Client端的功能方法

    private final Stub bookManager = new Stub() {…………}
    

    Client端 调用Stub类的静态方法asInterface,将Server端传递来的IBinder对象转换为Proxy对象

    private ServiceConnection serviceConnection = new ServiceConnection() {
            @Override
            public void onServiceConnected(ComponentName name, IBinder service) {
            ……
    		bookManager = Stub.asInterface(service);
            ……
    		}
    ……
    }
    

    其实,Proxy类只有两个成员变量:IBinder类对象remote,String类对象DESCRIPTOR(用于让Binder驱动 区分这个Proxy对象对应于哪个Binder Server)

    private static final String DESCRIPTOR = "com.baronzhang.ipc.server.BookManager";
    private IBinder remote;
    

    所以只用IBinder对象service,就能初始化一个Proxy对象了

    此外,服务端的Stub对象的onTransact()方法,会根据方法编号调用BookManager中的相关方法

  • Proxy:Server端定义的类,实现了BookManager接口
    Server端将一个 IBinder的实现类的对象 (下文简称IBinder对象)传递给客户端,客户端利用此IBinder对象,创建Proxy对象类的实例出现在Client端,代表Server端的 Stub对象的代理
    Proxy中实现的方法体,不实际处理任务,而是负责从客户端接收参数,交给服务端;再从服务端获取返回值,交给客户端

Binder、IBinder 和 IInterface 的关系:
参考https://blog.csdn.net/caoshen2014/article/details/99782563

关于AIDL

参考:https://juejin.cn/post/6844903496882323464

AIDL:Android Interface Define Language
AIDL代码遵循Java语法
AIDL代码存放在AIDLmodule中的.aidl文件里,需要经过AS的编译,才能转换为Java代码

Java层Binder实例代码分析

完整代码在:https://link.zhihu.com/?target=https%3A//github.com/BaronZ88/HelloBinder

IInterface : 是一个接口,代表Server 提供给Client的方法的集合

Binder : 一个类,实现了 IBinder 接口,Binder类对象应该出现在Server端

BookManager:Server端定义的接口,继承IInterface接口;定义Server端提供的功能,但不实现功能;
具体功能方法的实现,在Server端新建的Stub对象中
在这里插入图片描述
在这里插入图片描述
Stub:AIDL生成的类,实现BookManager接口,继承Binder类
在这里插入图片描述
客户端和服务端均可调用Stub类的方法。

Server端 在新建的Stub对象中,实现提供给Client端的功能方法

private final Stub bookManager = new Stub() {…………}

Client端 调用Stub类的静态方法asInterface,将Server端传递来的IBinder对象转换为Proxy对象

private ServiceConnection serviceConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
        ……
		bookManager = Stub.asInterface(service);
        ……
		}
……
}

其实,Proxy类只有两个成员变量:IBinder类对象remote,String类对象DESCRIPTOR(用于让Binder驱动 区分这个Proxy对象对应于哪个Binder Server)
所以只用IBinder对象service,就能初始化一个Proxy对象了

private static final String DESCRIPTOR = "com.baronzhang.ipc.server.BookManager";
private IBinder remote;

Proxy:Server端定义的类,实现了BookManager接口
在这里插入图片描述
Server端将一个 IBinder的实现类的对象 (下文简称IBinder对象)传递给客户端,客户端利用此IBinder对象,通过Stub.asInterface,创建Proxy对象:
在这里插入图片描述
类的实例出现在Client端,代表Server端的 Stub对象的代理

关于asInterface函数:
在这里插入图片描述

Proxy中实现的方法体,不实际处理任务,而是负责从客户端接收参数,交给服务端;再从服务端获取返回值,交给客户端

Stub类中,会对BookManager中的方法进行编号:
在这里插入图片描述

Proxy中调用transact进行分配:
private IBinder remote;
remote.transact(Stub.TRANSAVTION_getBooks, data, reply, 0);
在这里插入图片描述
最终调用到Stub的onTransact函数:
在这里插入图片描述

Native层Binder实现

参考:https://mr-cao.gitbooks.io/android/content/android-binder.html
在这里插入图片描述

C++中接口以抽象类的形式实现
抽象类:包含纯虚函数的类

IBinder、IInterface 都是抽象类
transact函数、onAsBinder函数是纯虚函数

IBinder是负责binder通信机制的基类,它有两个子类——BpBinder和BBinder。BpBinder代表着proxy,而BBinder代表着service。

  • BpXXXService是给binder client端用的(client进程中有BpXXXService实例)
  • BnXXXService和XXXService是给binder server端用的(server进程中有BnXXXService实例)
virtual status_t transact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0);

这是个纯虚函数,子类Bpbinder和BBinder负责它的具体实现。BpBinder的此函数负责传输数据,而BBinder的此函数是负责接收数据。关于此函数的参数的解释如下:

  • code:函数码值,告知service端请求执行的函数
  • data:保存执行函数所需的参数
  • reply:保存service函数返回的结果
  • flags:表示函数是同步调用还是异步调用。默认是同步调用,如果需要异步调用,flags需要被赋值为IBinder::FLAG_ONEWAY

在这里插入图片描述

IInterface::asBinder函数

参考:https://mr-cao.gitbooks.io/android/content/android-binder.html

class IInterface : public virtual RefBase{
public:
    IInterface();
    sp<IBinder> asBinder();
    sp<const IBinder> asBinder() const;

protected:
    virtual ~IInterface();
    virtual IBinder* onAsBinder() = 0;
};

IInterface 接口只有一个方法,asBinder
asBinder函数内部实际上是调用的虚函数virtual IBinder* onAsBinder() = 0,
onAsBinder这个纯虚函数是由子类BpInterface和BnInterface实现,可以从一个IInterfcae获得一个IBinder对象

template<typename INTERFACE>
IBinder* BnInterface<INTERFACE>::onAsBinder()
{
    return this;
}

template<typename INTERFACE>
inline IBinder* BpInterface<INTERFACE>::onAsBinder()
{
    return remote();
}
  • BnInterfce的onAsBinder函数是直接返回的this指针,因为BnInterfce是由IBinder继承而来
  • BpInterface的onAsBinder函数调用基类BpRefBase的remote函数,返回BpRefBase内部的mRemote指针,这个指针指向的是IBinder对象

鸡生蛋问题

参考https://www.jianshu.com/p/062a6e4f5cbe
ServiceManager和Binder驱动属于两个不同的进程,它们是为Client和Server之间的进程间通信服务的,也就是说Client和Server之间的进程间通信依赖ServiceManager和Binder驱动之间的进程间通信,这就像是:“蛋生鸡,鸡生蛋,但第一个蛋得通过一只鸡孵出来”。Binder机制是如何创造第一只下蛋的鸡呢?

当Android系统启动后,会创建一个名称为servicemanager的进程,这个进程通过一个约定的命令BINDERSETCONTEXT_MGR向Binder驱动注册,申请成为ServiceManager,Binder驱动会自动为ServiceManager创建一个Binder实体(第一只下蛋的鸡);
并且这个Binder实体的引用在所有的Client中都为0,也就说各个Client通过这个0号引用就可以和ServiceManager进行通信。Server通过0号引用向ServiceManager进行注册,Client通过0号引用就可以获取到要通信的Server的Binder引用。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Android BinderAndroid操作系统中的一个IPC(进程间通信)机制,用于实现进程之间的通信和数据传输。Binder的源码主要位于frameworks/native目录下。 在Binder的源码中,最核心的部分是Binder驱动和Binder服务。Binder驱动是位于内核空间的组件,负责处理进程间的数据传输和交互。Binder服务是位于用户空间的组件,负责提供接口和功能来进行进程间通信。 在Binder的源码中,主要涉及到以下几个重要的文件和目录: 1. drivers目录:包含了Binder驱动的代码,其中最重要的文件是binder.c,它实现了Binder驱动的核心逻辑。 2. include目录:包含了Binder的头文件,其中最重要的文件是binder.h,它定义了Binder的接口和数据结构。 3. libbinder目录:包含了Binder服务的代码,其中最重要的文件是IBinder.cpp和BpBinder.cpp,它们分别实现了Binder服务的接口和代理类。 4. services目录:包含了一些系统级别的Binder服务,例如Package Manager Service和Activity Manager Service。 如果你想深入了解Android Binder的源码,可以参考以下资源: 1. Android 源码:你可以从Android官网或者GitHub上获取Android源码,并在frameworks/native目录下查看Binder相关的代码。 2. Android系统架构指南:Android官网提供了关于Android系统架构的详细文档,其中有关IPC和Binder的章节对于理解Binder的实现原理和源码结构很有帮助。 3. 《深入理解Android:卷2》一书中有关于Binder的详细介绍和源码解析,可以作为参考资料。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值