Android 11(R) IPC Binder机制

一、为什么要使用Binder

Android 系统分为三层。最上层是application应用层,第二层是framework层,第三层是native层

1.Android 中的应用层和系统服务层不在同一个进程,系统服务在单独的进程中。每个应用的进程都是zygote fork出来的。

2.Android中不同应用属于不同的进程中

Android应用和系统services运行在不同的进程中是为了安全、稳定以及内存管理的原因,但是应用和系统服务需要通信和分享数据。 每个进程都单独运行,可以保证应用层对系统层的隔离,如果某个进程崩溃了不会导致其它进程崩溃。

3.内存划分

内存被操作系统划分成两块:用户空间和内核空间,用户空间是用户程序代码运行的地方,内核空间是内核代码运行的地方。为了安全,它们是隔离的,即使用户的程序崩溃了,内核也不受影响。

二、binder通信逻辑

SystemServer为了更好地管理系统服务,所以会有SystemServiceManager来辅助管理这些服务,AMS、ATMS、WMS都会有一个Lifecycle对象继承SystemService,通过SystemServiceManager达到间接管理服务的目的。一旦服务启动,会立刻将服务(Binder)传给ServiceManager进程进行保存。

三、Binder的创建

binder的创建通常是在进程创建的时候就创建了Binder,在frameworks/native/cmds/servicemanager/main.cpp中去初始化servicemanager进程,同时去初始化"/dev/binder"驱动。

APP进程 Binder的初始化逻辑和servicemanager 的初始化逻辑是一样的。APP进程的产生是在ZygoteInit中fork出来的。

最后会调用到nativeZygoteInit,在AndroidRuntime.cpp中可以看到对应的jni函数

根据函数最后可以看到创建ProcessState的对象,同时初始化了binder。

插入一道面试题,为什么Binder要在App进程初始化的第一时间创建?

答:因为APP进程创建之后会面临启动activity,activity通过AMS启动,因此,必须第一时间启动binder。

zygote进程有Binder吗?

答:zygote进程没有Binder,zygote是为了fork产生进程。因为fork时父进程不允许有多线程,因为有可能产生死锁。但是Binder的底层通信会创建线程。因此,zygote不允许用Binder。

四、Aidl跨进程通信原理

stub是服务的代理,service要访问binder,就会转交给stub完成,stub通过统一的形式进行,减少了我们服务封装驱动的过程。

proxy是服务端能够提供服务的代理,给client端使用。从代码可以看出,proxy是代理的stub,

五、bindservice跨进程通信流程

applicationThread也有stub,因此ams才能通过binder访问到server和client。

六、Binderproxy Client Native层

1. app binder 调用服务端接口流程

service.notify() (notify为aidl中的函数接口)  -》

IXXX.Stub.Proxy.notify() -》

BinderProxy.transact()    -》

android_util_Binder.android_os_BinderProxy_transact -》

 BpBinder.transact-》 

 IPCThreadState.transact -》 

waitForResponse -》

 IPCThreadState::talkWithDriver -》

 ioctl

IPCThreadState是创建IPC线程进行通信,talkWithDriver是与驱动进行通信,读驱动数据。

2. Clinet端调度流程

例如

ActivityManager.java.getService() -》 

ServiceManager.java.getService -》

ServiceManager.java.rawGetService -》

getIServiceManager() -》

BinderInternal.getContextObject() -》 

 native getContextObject -》android_util_Binder.cpp.android_os_BinderInternal_getContextObject -》 

ProcessState.getContextObject -》 

ProcessState.getStrongProxyForHandle(0) -》 

javaObjectForIBinder -》 

env->CallStaticObjectMethod(gBinderProxyOffsets.mClass,

            gBinderProxyOffsets.mGetInstance, (jlong) nativeData, (jlong) val.get());  (反射)-》

gBinderProxyOffsets.mGetInstance = GetStaticMethodIDOrDie(env, clazz, "getInstance",

            "(JJ)Landroid/os/BinderProxy;"); -》

BinderProxy.java.getInstance。 

最后返回bpbinder封装出来的binderproxy对象。

3. bpbinder封装逻辑

getIServiceManager().getService(name)同 (ServiceManagerProxy  IServiceManager.Stub.Proxy类).getService(name)-》

IServiceManager.java.getService-》

BinderProxy.java.transact-》

 native transactNative-》

android_util_Binder.cpp . android_os_BinderProxy_transact-》

BpBinder::transact-》

IPCThreadState::self()-》

transact-》

writeTransactionData(写入序列化数据)-》

waitForResponse-》

talkWithDriver-》

ioctl

process是一个进程,ProcessState每个进程在初始化时都会拉起。

4. Service端调度流程

以servicemanager为例进行解析

ServiceManager是一个进程,是由init进程启动的,早于zygote进程。

在init进程中,在SecondStageMain的LoadBootScripts(am, sm);中会去解析init.rc,在init.rc中有一段语句    start servicemanager。servicemanager同时也有自己的rc文件,

user system 说明这个进程是以系统身份来运行的。

class core animation

将此服务归类为 coreanimation 类别。core 类别表示这是一个核心服务,animation 类别可以与系统动画相关的服务。

user system
group system readproc
将此服务设置为以 system 用户身份运行,并属于 system 组。同时,该服务也属于 readproc 组,允许其读取 /proc 文件系统中的信息。

critical

标记此服务为关键服务。如果此服务崩溃,系统将会重启。

onrestart restart healthd
onrestart restart zygote
onrestart restart audioserver
onrestart restart media
onrestart restart surfaceflinger
onrestart restart inputflinger
onrestart restart drm
onrestart restart cameraserver
onrestart restart keystore
onrestart restart gatekeeperd
onrestart restart thermalservice

servicemanager 重启时,以上列出的服务也会被重启

shutdown critical

当系统关机时,servicemanager 将被视为关键服务并进行相应处理

在servicemanager中,会实例化一个servicemanager对象,这个对象的继承自BBinder。因此,servicemanager实际上是一个Bbinder的接口。

class ServiceManager : public os::BnServiceManager, public IBinder::DeathRecipient {...}

class BnServiceManager : public ::android::BnInterface<IServiceManager> {...}

class IServiceManager : public IInterface {...}

template<typename INTERFACE>  class BnInterface : public INTERFACE, public BBinder {...}

继承关系图如下:

设置服务端Bbinder对象

代码中    IPCThreadState::self()->setTheContextObject(manager);这一句设置了下面流程图中服务端的BBinder对象,

    //通过Looper epoll机制处理binder事务
    sp<Looper> looper = Looper::prepare(false /*allowNonCallbacks*/);

    BinderCallback::setupTo(looper);
    ClientCallbackCallback::setupTo(looper, manager);

    while(true) {
        looper->pollAll(-1);
    }
class BinderCallback : public LooperCallback {
public:
    static sp<BinderCallback> setupTo(const sp<Looper>& looper) {
        sp<BinderCallback> cb = new BinderCallback;

        int binder_fd = -1;
        //向binder驱动发送BC_ENTER_LOOPER事务请求,并获得binder设备的文件描述符
        IPCThreadState::self()->setupPolling(&binder_fd);
        LOG_ALWAYS_FATAL_IF(binder_fd < 0, "Failed to setupPolling: %d", binder_fd);

        // Flush after setupPolling(), to make sure the binder driver
        // knows about this thread handling commands.
        //检查写缓存是否有可写数据,有的话发送给binder驱动
        IPCThreadState::self()->flushCommands();
        //监听binder文件描述符
        int ret = looper->addFd(binder_fd,
                                Looper::POLL_CALLBACK,
                                Looper::EVENT_INPUT,
                                cb,
                                nullptr /*data*/);
        LOG_ALWAYS_FATAL_IF(ret != 1, "Failed to add binder FD to Looper");

        return cb;
    }
    //当binder驱动发来消息后,就可以通过Looper::handleEvent函数接收并处理了
    int handleEvent(int /* fd */, int /* events */, void* /* data */) override {
        //从binder驱动接收到消息并处理
        IPCThreadState::self()->handlePolledCommands();
        return 1;  // Continue receiving callbacks.
    }
};

binder数据一次能传送的数据是1M-8k。

5. 服务端如何完成通信

每当客户端发送消息给驱动,驱动会把消息转到BinderCallback中的

    int handleEvent(int fd, int /*events*/, void* /*data*/) override {...}

进行处理。

BinderCallback->handleEvent-》

status_t IPCThreadState::handlePolledCommands()-》

getAndExecuteCommand->executeCommand-》

case BR_TRANSACTION: the_context_object->transact-》

BBinder::transact-》

BBinder::onTransact-》

IServiceManager.cpp.BnServiceManager::onTransact-》

ServiceManager.cpp.ServiceManager::getService-》

tryGetService-》

mNameToService.find(name);

可以看到这里维持了一个表。存储binder和对应字符串。

6. 服务端总结:

驱动ioctl -> LooperCallback -> IPCThreadState::self()->handlePolledCommands() -> Bbinder ->transact  -> BnServiceManager::onTransact -> ServiceManager.getService

  • 19
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值