Android 11(R) IPC Binder机制 初版

news2024/9/17 7:48:24

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

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

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

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

内存划分

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

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层

app binder 调用服务端接口流程

service.notify()->IXXX.Stub.Proxy.notify()->BinderProxy.transact()->android_util_Binder.android_os_BinderProxy_transact->BpBinder.transact->IPCThreadState.transact->waitForResponse->IPCThreadState::talkWithDriver->ioctl

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

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对象。

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每个进程在初始化时都会拉起。

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。

服务端如何完成通信

每当客户端发送消息给驱动,驱动会把消息转到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和对应字符串。

服务端总结:

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1958792.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

数据驱动未来:构建下一代湖仓一体电商数据分析平台,引领实时商业智能革命

1.1 项目背景 本项目是一个创新的湖仓一体实时电商数据分析平台&#xff0c;旨在为电商平台提供深度的数据洞察和业务分析。技术层面&#xff0c;项目涵盖了从基础架构搭建到大数据技术组件的集成&#xff0c;采用了湖仓一体的设计理念&#xff0c;实现了数据仓库与数据湖的有…

《程序猿入职必会(4) · Vue 完成 CURD 案例 》

&#x1f4e2; 大家好&#xff0c;我是 【战神刘玉栋】&#xff0c;有10多年的研发经验&#xff0c;致力于前后端技术栈的知识沉淀和传播。 &#x1f497; &#x1f33b; CSDN入驻不久&#xff0c;希望大家多多支持&#xff0c;后续会继续提升文章质量&#xff0c;绝不滥竽充数…

【优选算法】——leetcode——438.找到字符串中所有字母异位词

目录 1.题目 2.题目理解 3.算法原理 1.如何快速判断两个字符串是否是异位词 2.解决问题 暴力求解——>滑动窗口哈希表 滑动窗口 利用滑动窗口哈希表解决问题 优化&#xff1a;更新结果的判断条件 4.编程代码 C代码 1.频率统计 2. 双指针 C语言代码 1.字符频率…

传统CS网络的新生——基于2G网络的远程灌溉实现

概述&#xff1a;iphone 实现远程电话触发&#xff0c;实现灌溉绿植的一般方法 方法一&#xff1a; 远程电话触发&#xff0c;音频线左右声道会产生一个信号&#xff0c;可以在后端利用SR锁存器暂存信号&#xff0c;后级可以接相应的控制电路实现灌溉。 方法二&#xff1a; 同…

记录阮一峰grid教程笔记

前言 看了阮一峰的grid教程&#xff0c;做一个笔记&#xff0c;主要自己看&#xff0c;有理解错误的地方后续更正&#xff0c;有新的理解后续补充。教程链接如下&#xff1a; CSS Grid 网格布局教程 - 阮一峰的网络日志 grid主要分为容器属性和项目的属性&#xff0c;在行列布…

React 学习——Context机制层级组件通信

核心思路&#xff1a;&#xff08;适用于所有层级&#xff0c;不仅仅是爷孙 父子&#xff09; createContext方法创建一个上下文对象在顶层组件 通过Provider组件提供数据在底层组件&#xff0c;通过useContext钩子函数使用数据 import { createContext, useContext } from …

NSSRound#4 Team

[NSSRound#4 SWPU]1zweb 考察&#xff1a;phar的反序列化 1.打开环境&#xff0c;审计代码 1.非预期解 直接用file伪协议读取flag,或直接读取flag file:///flag /flag 2.正常解法 用读取文件读取index.php,upload.php的源码 index.php: <?php class LoveNss{publi…

Java面试八股之Spring DAO的作用

Spring DAO的作用 Spring DAO (Data Access Object) 是 Spring 框架的一个重要组成部分&#xff0c;它提供了一套用于简化数据访问操作的抽象层。Spring DAO 的核心目的是使开发人员能够更容易地处理数据访问相关的异常&#xff0c;并提供一致的异常处理机制&#xff0c;同时简…

翻译: 可视化深度学习神经网络一

这是一个随意书写的28*28像素、分辨率很低的数字 3 但你的大脑一看见就能轻松辨识出来 &#xff0c;我想要你好好欣赏这点 人脑能够毫无障碍地辨识是非常厉害的 我的意思是&#xff0c;这个、这个、还有这个&#xff0c;都能被识别为 3 即使前后图像的图形组成有很大差异 当你…

什么情况?我代码没了

前两天检视代码时&#xff0c;发现PR里面有两个提交的描述信息一模一样&#xff0c;于是我提出应该将这两个提交合并成一个&#xff0c;保持提交树的清晰。 1 先储存起来&#xff01; 而同事这时正在开发别的特性&#xff0c;工作区不是干净的&#xff0c;没法直接执行 git r…

c程序杂谈系列(职责链模式与if_else)

从处理器的角度来说&#xff0c;条件分支会导致指令流水线的中断&#xff0c;所以控制语句需要严格保存状态&#xff0c;因为处理器是很难直接进行逻辑判断的&#xff0c;有可能它会执行一段时间&#xff0c;发现出错后再返回&#xff0c;也有可能通过延时等手段完成控制流的正…

python生成二维码指向说明书

python生成二维码转向文档 python生成二维码指向说明书 import qrcode# 生成包含本地文档路径的二维码 def generate_qrcode(local_file_path):qr qrcode.QRCode(version1,error_correctionqrcode.constants.ERROR_CORRECT_L,box_size10,border4,)qr.add_data(local_file_pa…

为什么要做边界值测试?

边界值测试的理解 边界值测试&#xff08;Boundary Value Testing&#xff09;是一种常用的软件测试方法&#xff0c;它侧重于测试输入值的边缘或临界条件。这些边缘条件通常包括最小值、最大值以及接近这些最小值和最大值的值。边界值测试的基本思想是&#xff0c;许多软件错…

微信支付API列表

接入前准备 更新时间&#xff1a;2023.08.24 在正式接入微信支付App服务前&#xff0c;你需要进行以下准备步骤&#xff1a; 选择接入模式&#xff1a;普通商户或普通服务商申请参数&#xff1a;AppID、商户号App支付页面规范 #选择接入模式 商户需要判断自己公司注册区域…

SuperMap GIS基础产品FAQ集锦(20240729)

一、SuperMap iDesktopX 问题1&#xff1a;您好&#xff0c;想请教一下&#xff0c;白模可以调整颜色吗 11.2.0 【解决办法】 右键白模图层&#xff0c;制作单值专题图&#xff0c;即可调整白模颜色。 问题2&#xff1a;这边有份矢量数据&#xff0c;导入到桌面里面要放很大…

Node.js + Axios 上传附件到 Gitee 仓库指定 Release

在软件开发过程中&#xff0c;自动化发布流程是提升效率的关键环节之一。本文将介绍如何使用 Node.js 和 Axios 库来自动化地向 Gitee 仓库的最新版本中上传发布包。通过读取项目中的 package.json 文件&#xff0c;获取版本信息&#xff0c;并自动将构建好的包文件上传到 Gite…

我们的前端开发逆天了!1 小时搞定了新网站,还跟我说 “不要钱”

大家好&#xff0c;我是程序员鱼皮。前段时间我们上线了一个新软件 剪切助手 &#xff0c;并且针对该项目做了一个官网&#xff1a; 很多同学表示官网很好看&#xff0c;还好奇是怎么做的&#xff0c;其实这个网站的背后还有个有趣的小故事。。。 鱼皮&#xff1a;我们要做个官…

【gofar远为门锁】酒店智能门锁源码 对接收银CyberWinApp-SAAS本地化-未来之窗行业应用跨平台架构

通过写房卡按钮写房卡 一、查看门锁读卡器信息 二、玄武星辰查到对应名称 如何知道自己家门锁的app&#xff0c;使用未来之窗【玄武芯辰】查询 通过上面我看出叫做gofar 在【玄武芯辰】输入gofar&#xff0c;人工智能会提示app信息 三、设置门锁控制app 在上一步找到app&a…

web服务器配置-(apache+nginx)

⼀、web基本概念和常识 Web&#xff1a;为⽤户提供的⼀种在互联⽹上浏览信息的服务&#xff0c;Web 服务是动态的、可交互的、跨平台的和图形化的。 Web 服务为⽤户提供各种互联⽹服务&#xff0c;这些服务包括信息浏览服务&#xff0c;以及各种交互式服务&#xff0c;包括聊…

LinuxCentos中安装apache网站服务详细教程

&#x1f3e1;作者主页&#xff1a;点击&#xff01; &#x1f427;Linux基础知识(初学)&#xff1a;点击&#xff01; &#x1f427;Linux高级管理防护和群集专栏&#xff1a;点击&#xff01; &#x1f510;Linux中firewalld防火墙&#xff1a;点击&#xff01; ⏰️创作…