IBinder源码分析

基础概念

  • binder 是 Android 中主要的跨进程通信方式,binder 驱动和 service manager 分别相当于网络协议中的路由器和 DNS,并基于 mmap 实现了 IPC 传输数据时只需一次拷贝。
  • binder 包括 BinderProxy、BpBinder 等各种 Binder 实体,以及对 binder 驱动操作的 ProcessState、IPCThreadState 封装,再加上 binder 驱动内部的结构体、命令处理,整体贯穿 Java、Native 层,涉及用户态、内核态,往上可以说到 Service、AIDL 等,往下可以说到 mmap、binder 驱动设备,是相当庞大、繁琐的一个机制。
  • 从不同的层面分析Binder有不同的解释
    • 机制:Binder是一种进程间通信机制
    • 驱动:Binder是一个虚拟物理驱动设备
    • 应用层:Binder是一个能发起通信的Java类

进程隔离

进程隔离简单的说就是 Linux 操作系统设计的一种机制,使进程之间不能共享数据,保持各自数据的独立性,即A进程不能访问B进程数据,同理B进程也不能访问A进程数据。通过虚拟内存技术,达到 Linux 进程中数据不能共享,从而保持独立的功能。所以,Linux 进程之间要进行数据交互就得采用特殊的通信机制,即 IPC 通信!
进程隔离的优点:

  • 稳定性:进程独立,保证一个进程的崩溃不会引起其他进程的崩溃
  • 安全性:保护各个进程数据的独立性

Linux内存管理单元

内核空间&用户空间

  • 内核空间
    • Linux内核的运行空间,Linux操作系统和驱动程序均运行在内核空间,其中虚拟内存0XC0000000~0XFFFFFFFF供内核使用,称为内核空间
  • 用户空间
    • 用户程序的运行空间,运行这App,其中虚拟内存地址0X000000~0XBFFFFFFF供各个进程使用,称为用户空间
  • 为什么区分内核空间和用户空间
    • 隔离应用程序和系统程序,使得应用程序的崩溃不会造成内核的崩溃,即应用的崩溃不会导致程序的死机崩溃
    • 每个应用程序活进程都会有自己的特定地址和私有数据空间,保证程序之间不会相互影响
    • 提供了系统的稳定性

内存管理单元

MMU(Memory Management Unit)主要用来管理虚拟存储器、物理存储器的控制线路,同时也负责虚拟地址映射为物理地址,以及提供硬件机制的内存访问授权、多任务多进程操作系统。

  • 相关概念
    • 地址范围
      • 指处理器能够产生的地址集合
    • 物理地址&物理地址空间
      • 物理地址:CPU地址总线传来的地址,由硬件电路控制其具体含义。物理地址中很大一部分是留给内存条中的内存的,但也常被映射到其他存储器上(如显存、BIOS等)。在程序指令中的虚拟地址经过段映射和页面映射后,就生成了物理地址,这个物理地址被放到CPU的地址线上。
      • 物理地址空间:一部分给物理RAM(内存)用,一部分给总线用,这是由硬件设计来决定的,因此在32 bits地址线的x86处理器中,物理地址空间是2的32次方,即4GB,但物理RAM一般不能上到4GB,因为还有一部分要给总线用(总线上还挂着别的 许多设备)。在PC机中,一般是把低端物理地址给RAM用,高端物理地址给总线用。
    • 虚拟地址&虚拟地址空间
      • 虚拟地址:现代操作系统普遍采用虚拟内存管理(Virtual Memory Management)机制,这需要MMU(Memory Management Unit)的支持。MMU通常是CPU的一部分,如果处理器没有MMU,或者有MMU但没有启用,CPU执行单元发出的内存地址将直接传到芯片引脚上,被 内存芯片(物理内存)接收,这称为物理地址(Physical Address),如果处理器启用了MMU,CPU执行单元发出的内存地址将被MMU截获,从CPU到MMU的地址称为虚拟地址(Virtual Address),而MMU将这个地址翻译成另一个地址发到CPU芯片的外部地址引脚上,也就是将虚拟地址映射成物理地址。
      • 虚拟地址空间:操作系统会给每个进程分配一个虚拟地址空间(vitural address),每个进程包含的栈、堆、代码段这些都会从这个地址空间中被分配一个地址,这个地址就被称为虚拟地址。底层指令写入的地址也是虚拟地址
  • 页的基本结构
    在这里插入图片描述
    为了CPU的高效执行以及方便的内存管理,每次需要拿一个页的代码。这个页,指的是一段连续的存储空间(常见的是4Kb),也叫作块。
    • 在任何时刻,虚拟页都是以下三种状态中的一种:
      • 未分配的:VM系统还未分配的页(或者未创建)。未分配的页还没有任何数据与代码与他们相关联,因此也就不占用任何磁盘。
      • 缓存的: 当前已缓存在物理内存中的已分配页
      • 未缓存的:未缓存在物理内存中的已分配页
  • 页表的基本结构
    在这里插入图片描述
    页表实际上就是一个数组。这个数组存放的是一个称为页表条目(PTE)的结构。虚拟地址空间的每一个页在页表中,都有一个对应的页表条目(PTE)。虚拟页地址(首地址)翻译的时候就是查询的各个虚拟页在页表中的PTE,从而进行地址翻译的。现在假设每一个PTE都有一个有效位和一个n位字段的地址。
    • 有效位:表示对应的虚拟页是否缓存在了物理内存中。0表示未缓存。1表示已缓存。
    • n位地址字段:如果未缓存(有效字段为0),n位地址字段不为空的话,这个n位地址字段就表示该虚拟页在磁盘上的起始的位置。如果这个n位字段为空,那么就说明该虚拟页未分配。如果已缓存(有效字段为1),n位地址字段肯定不为空,它表示该虚拟页在物理内存中的起始地址。

关键说明

  • Android为什么使用binder进行进程通信
    • Linux进程通信的方式以及弊端
通信方式效率安全模型
管道低(两次copy)安全支持1对1
共享内存最高(内存共享)不安全支持N对N
Socket不安全C/S
File低(文件读写)不安全支持N对N
  • Binder&共享内存&Socket对比
Binder共享内存Socket
性能一次copy(copy_from_user)无需copy两次copy(copy_from_user,copy_to_user)
特点基于C/S架构,易用性高控制复杂,易用性低基于C/S架构,易用性低
安全性为每个App分配UID,同时支持实名和匿名依赖上层协议,访问接入点是开放的,不安全依赖上层协议,访问接入点是开放的,不安全

进程通信

  • Linux进程通信流程
    在这里插入图片描述

  • Binder进程通信流程
    在这里插入图片描述

关键问题

  • Binder如何做到一次拷贝
    • 首先Binder驱动在内核空间创建一个数据接收缓存区;
    • 接着在内核空间开辟一块内核缓存区,建立内核缓存区和内核中数据接收缓存区之间的映射关系,以及内核中数据接收缓存区和接收进程用户空间地址的映射关系;
    • 发送方进程通过系统调用 copy_from_user() 将数据 copy 到内核中的内核缓存区,由于内核缓存区和接收进程的用户空间存在内存映射,因此也就相当于把数据发送到了接收进程的用户空间,这样便完成了一次进程间的通信
  • mmap原理
    • 进程启动后会在虚拟内存空间中串讲虚拟映射区域,即进程在用户空间调用库函数mmap (void *mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset)😉,找到满足需求的连续的虚拟地址,并对该虚拟区进行初始化
    • 调用内核空间的系统调用函数mmap(不同于用户空间函数)实现文件物理地址和进程虚拟地址的一一映射关系
    • 进程发起对这片映射空间的访问,引发缺页异常,实现文件内容到物理内存(主存)的拷贝
  • Binder传输数据的大小限制是多少:1M-8K
    • ProcessState.cpp中初始化BInder服务时限制了其大小为1MB-4KB*2 (pagesize是申请物理内存的最小单元,大小为4K)
    • 理论上这个限制是可以重新设置的,可以通过调用binder_open和binder_mmap进行修改大小限制,但是会导致Binder驱动的重启,因为APP和其他应用,AMS,WMS的交互可都是依赖于Binder通信,重启必会引起其他不可预估的问题,所以不建议进行该操作
//ProcessState.cpp中初始化BInder服务
#define BINDER_VM_SIZE ((1 * 1024 * 1024) - sysconf(_SC_PAGE_SIZE) * 2)//这里的限制是1MB-4KB*2ProcessState::ProcessState(const char *driver)
{if (mDriverFD >= 0) {// mmap the binder, providing a chunk of virtual address space to receive transactions.// 调用mmap接口向Binder驱动中申请内核空间的内存mVMStart = mmap(0, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);if (mVMStart == MAP_FAILED) {// *sigh*ALOGE("Using %s failed: unable to mmap transaction memory.\n", mDriverName.c_str());close(mDriverFD);mDriverFD = -1;mDriverName.clear();}}
}
  • AIDL生成java类的细节
    • 其中Stub类继承自Binder,内部有个onTransact方法,当跨进程远程调用服务端方法的时候,这个方法会被调用,在这个方法里会判断要请求的是哪个方法,然后调用服务端中这个Stub类的实现类中的方法;并将要返回的结果写入Parcel对象中
    • Proxy代理类是用于代理Binder对象进行跨进程访问,当调用代理类的方法时,内部会先将要请求的参数写入Parcel对象中,然后调用Binder的transact方法进行远程调用并返回结果
    • 当调用Binder的transact方法后,底层会通过BpBinder封装数据后转发远程调用请求,然后将数据拷贝到内核层,通过Binder驱动转发给服务端,服务端进程那边会通过BbBinder对数据进行解析,最终调用服务端Stub实现类里的onTransact方法
  • Android APP有多少Binder线程,是固定的么
    • app启动时在创建进程时默认会创建一个Binder主线程在运行,如果App中定义个其他服务在独立进程中,每个进程都至少会启动一个Binder主线程,后面根据跨进程通信请求次数,Binder会自动调成线程个数
    • 最大的Binder线程也不是固定的,在ProcessState类中定义的默认最大线程个数是15个,这15个(不包括主Binder线程和将当前线程加入到Binder线程池中的),这个最大线程个数是可以修改的,比如SystemServer中就将线程池线程最大个数改成了31个
  • bindService启动Service与Binder服务实体的流程
    • 客户端调用bindService方法后,会跨进程调用AMS方法去查找要启动服务的信息,判断对应的服务所在进程是否已经启动,如果还没有则先通知Zygote启动进程
    • 进程启动后会检查对应的Service是否已经创建,如果没有的话会通知ActivityThread先创建服务,创建完了之后会调用它的生命周期方法onCreate和onBind,在onBind方法中服务端会实现Stub类,这个Stub类继承自Binder
    • 然后Service所在进程会将Binder对象返回给AMS,ANS则会回调客户端的ServiceConnection接口的onServiceConnected方法,并把服务端onBind方法返回的Binder对象返回给客户端客户端拿到Binder对象后调用asInterface方法,这个方法里会根据是否跟服务端在一个进程中,来决定是返回服务端接口本身,还是返回支持跨进程通信的代理类Proxy
    • 接着客户端就可以直接调用Service提供的方法了
  • 为什么内核有内核缓存区还要有个数据接收缓存区?
    • 因为内核缓冲区是一直就存在的,以往的跨进程通信就是先从发送方拷贝到内核缓存区,然后再拷贝到接收方,所以需要两次拷贝,Binder的出现创建了一块数据接收缓存区,通过mmap将接收方和系统内核缓存区连接起来,从而减少了一次拷贝
  • Binder如何找到目标进程
    • binder服务会事先在Binder驱动的红黑树中注册结点,当跨进程通信时Binder驱动会先从红黑树中查找目标Binder所在结点,从结点中获取进程、线程信息,然后去唤醒目标进程、线程

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

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

相关文章

PDF Reader Pro for mac激活版 PDF编辑阅读器

PDF Reader Pro阅读器是一款用户必备的集管理、编辑、转换、阅读功能于一体的专业的全能PDF阅读专家。快速、易用、强大,让您出色完成 PDF 工作,深受全球9000万用户的喜爱。用户可轻松使用PDF Reader Pro进行文档阅读、编辑、注释、填写Form表单、转换、…

图像分割从基础到进阶:阈值化、K-means和Mean-Shift算法的应用

图像分割是计算机视觉中的一项关键技术,用来将图像划分为若干个 有意义 的区域,以便后续的图像处理和分析工作。根据任务的不同,图像分割可以进一步细分为语义分割、实例分割和全景分割: 语义分割 (Semantic Segmentation) 对图像…

生产消费者模型

线程同步 互斥锁(互斥量)条件变量生产/消费者模型 一、互斥锁 C11提供了四种互斥锁: mutex:互斥锁。timed_mutex:带超时机制的互斥锁。recursive_mutex:递归互斥锁。recursive_timed_mutex:带超时机制的递归互斥锁…

国标GB28181视频平台EasyCVR私有化视频平台工地防盗视频监控系统方案

一、方案背景 在当代建筑施工领域,安全监管和防盗监控是保障工程顺利进行和资产安全的关键措施。随着科技进步,传统的监控系统已不足以应对现代工地的安全挑战。因此,基于国标GB28181视频平台EasyCVR的工地防盗视频监控系统应运而生&#xf…

WindowsDocker安装到D盘,C盘太占用空间了。

Windows安装 Docker Desktop的时候,默认位置是安装在C盘,使用Docker下载的镜像文件也是保存在C盘,如果对Docker使用评率比较高的小伙伴,可能C盘空间,会被耗尽,有没有一种办法可以将Docker安装到其它磁盘,同时Docker的数据文件也保存在其他磁盘呢? 答案是有的,我们可以…

【AI日记】24.11.01 LangChain、openai api和github copilot

【AI论文解读】【AI知识点】【AI小项目】【AI战略思考】【AI日记】 工作 工作1 内容:学习deeplearning.ai的免费课程地址:LangChain Chat with Your DataB站地址:https://www.bilibili.com/video/BV148411D7d2github代码:https:…

HTML静态网页成品作业(HTML+CSS)——花主题介绍网页设计制作(1个页面)

🎉不定期分享源码,关注不丢失哦 文章目录 一、作品介绍二、作品演示三、代码目录四、网站代码HTML部分代码 五、源码获取 一、作品介绍 🏷️本套采用HTMLCSS,未使用Javacsript代码,共有1个页面。 二、作品演示 三、代…

WinCC V7.5 SP1VBS全局变量的使用

1 <概述> 在 WinCC 使用过程中&#xff0c;有很多应用场合需要把获得的数据保存下来&#xff0c;在其它事件 中来使用&#xff0c;例如在 WinCC 运行后去读取自定义的配置文件中的参数&#xff0c;在控制相应设 备时需要根据这些参数来确定控制方式&#xff0c;那么就需…

Charles抓包_Android

1.下载地址 2.破解方法 3.安卓调试办法 查看官方文档&#xff0c;Android N之后抓包要声明App可用User目录下的CA证书 3.1.在Proxy下进行以下设置&#xff08;路径Proxy->Proxy Settings&#xff09; 3.1.1.不抓包Windows&#xff0c;即不勾选此项&#xff0c;免得打输出不…

微信小程序 高校教材征订系统

文章目录 项目介绍具体实现截图技术介绍mvc设计模式小程序框架以及目录结构介绍错误处理和异常处理java类核心代码部分展示详细视频演示源码获取 项目介绍 系统分为三个角色&#xff0c;分别是教材科、系教学秘书、教研室主任。系统主要完成功能是教材科要发布教材征订信息&am…

Rust 力扣 - 1343. 大小为 K 且平均值大于等于阈值的子数组数目

文章目录 题目描述题解思路题解代码题目链接 题目描述 题解思路 长度为k且平均值大于等于阈值的子数组数目 等于 长度为k且总和大于等于k * 阈值的子数组数目 我们遍历长度为k的窗口&#xff0c;我们只需要记录窗口内的总和即可&#xff0c;遍历过程中记录总和大于等于k * 阈…

3DMax使用 MCG实现简单克隆修改器

3DMax中的MCG工具集允许用户创建几种不同类型的插件。在这个例子中&#xff0c;我们正在创建一个简单的克隆修改器。 将修改器添加到对象时&#xff0c;将使用“数量”整数值克隆网格n次&#xff0c;并使用X、Y和Z中的“缩放”、“旋转”和“移动”微调器控制每个网格的偏移。…

收卷锥度张力控制(Simulink建模)

1、收卷锥度张力控制功能块(支持5种锥度曲线) 收卷锥度张力控制功能块(支持5种锥度曲线)-CSDN博客文章浏览阅读340次。1、锥度张力控制张力锥度控制(收卷应用)-CSDN博客文章浏览阅读2.2k次。收卷、放卷应用系列文章可以参看下面的文章链接:变频器简单张力控制(线缆收放卷…

【星闪EBM-H63开发板】小熊派固件中心的使用

目录 引言 固件中心 定制固件 创建配置 透传固件的配置信息 串口配置 SLE无线射频配置 SLE连接配置 硬件配置 生成固件 下载和烧录 结语 引言 前面几天介绍了星闪EBM-H63开发板的情况&#xff0c;今天来试试固件中心。 固件中心 固件中心是小熊派提供的用于生成固…

从《Mixtral of Experts》开始讲讲MoE

MoE 在讲这篇论文前先来说说什么是MoE MoE是什么&#xff1f; MoE&#xff0c;全称Mixture of Experts&#xff0c;混合专家模型。MoE是大模型架构的一种&#xff0c;其核心工作设计思路是“术业有专攻”&#xff0c;即将任务分门别类&#xff0c;然后分给多个“专家”进行解…

Java打造智能语音陪聊软件?提升用户体验的新路径

在现在的日常生活中&#xff0c;大家做什么都会寻找一个“搭子”&#xff0c;例如“游戏搭子”&#xff0c;很多时候一时半会找不到就会很苦恼&#xff0c;就因此诞生了语音陪聊软件。然而Java作为一种广泛使用的编程语言&#xff0c;在开发高效、稳定的应用程序方面具有显著优…

js.轮转数组和旋转链表

这是两个相似的题型&#xff0c;一个是数组&#xff0c;另一个是链表。 链接&#xff1a;189. 轮转数组 - 力扣&#xff08;LeetCode&#xff09; 题目&#xff1a; 给定一个整数数组 nums&#xff0c;将数组中的元素向右轮转 k 个位置&#xff0c;其中 k 是非负数。 示例 1:…

004-Kotlin界面开发快速入水之TicTacToe

程序界面和效果 快速入水 要学习一样跟程序设计有关的东西&#xff0c;最好的办法始终是把手打湿&#xff0c;整一个能够运行&#xff0c;可以实验的东西出来。 也只有在程序开发中&#xff0c;我们才能想一个魔法师而不是魔术师&#xff0c;我们真的能够创造一个东西。而且编…

Spring Boot——日志介绍和配置

1. 日志的介绍 在前面的学习中&#xff0c;控制台上打印出来的一大堆内容就是日志&#xff0c;可以帮助我们发现问题&#xff0c;分析问题&#xff0c;定位问题&#xff0c;除此之外&#xff0c;日志还可以进行系统的监控&#xff0c;数据采集等 2. 日志的使用 在程序中获取日…

python opencv2

二、图像预处理 1、图像翻转 cv2.flip(src, flipCode) &#xff1a;flipCode &#xff1a;0&#xff1a;沿 X 轴翻转&#xff08;垂直翻转&#xff09;&#xff1b;1&#xff1a;沿 Y 轴翻转&#xff08;水平翻转&#xff09;&#xff0c;-1&#xff1a;沿 X 轴和 Y 轴翻转&am…