Android Binder机制

article/2025/10/29 0:37:01

Android Binder机制

  • 什么是Binder
  • Binder
    • 一般的IPC原理
    • 动态内核可加载模块
    • 内存映射
    • 运行机制
      • 四大角色
      • 注册服务
      • 使用服务
    • 对象的传递
    • Binder通信

什么是Binder

要理解binder,先要知道IPC,Inter-process communication ,也就是进程中相互通信,Binder是Android提供的一套进程间相互通信框架。用来多进程间发送消息,同步和共享内存。

Linux中进程通信的方式主要有:

  • 管道:在创建时分配一个page大小的内存,缓存区大小比较有限,速度慢;

  • 消息队列:信息复制两次,额外的CPU消耗;不合适频繁或信息量大的通信;

  • 共享内存:无须复制,共享缓冲区直接付附加到进程虚拟地址空间,速度快;但进程间的同步问题操作系统无法实现,必须各进程利用同步工具解决;

  • 套接字:作为更通用的接口,传输效率低,主要用于不通机器或跨网络的通信;

  • 信号量:常作为一种锁机制,防止某进程正在访问共享资源时,其他进程也访问该资源。因此,主要作为进程间以及同一进程内不同线程之间的同步手段。

  • 信号: 不适用于信息交换,更适用于进程中断控制,比如非法内存访问,杀死某个进程等;统的进程间通信可能会增加进程的开销,而且有进程过载和安全漏洞等方面的风险,Binder

Android系统中的Binder框架图如下:
Alt
拿Activity举例从上图可以看出来:Activity是由ActivityManager来控制的,而ActivityManager其实是通过Binder获取ActivityManagerService服务来控制Activity的,并且ActivityManager是Android系统FrameWork层的,和应用中的activity不是同一个进程。

重点:

  1. Binder是Android提供的一套进程间通信框架。
  2. 系统服务ActivityManagerService,LocationManagerService,等都是在单独进程中的,使用binder和应用进行通信。

Binder

一般的IPC原理

  • 发送:首先会将要发送的数据放到内存缓存区,通过系统调用进入内核态,内核空间会开辟一块缓存区,通过copyfromuser()将用户空间的数据拷贝到内核空间的缓存区。

  • 接收:接收方的用户进程里,开辟一块内存缓存区,内核调用copytouser()将数据从内核缓存区拷贝到接收进程开辟的内存缓存区。
    以上便完成了一次进程间的通信,但是存在下面的不足:

在性能上,需要两次的数据拷贝:用户->内核、内核->用户
由于接收的用户进程无法知道接收的数据多大,所以它只能开辟尽可能大的内存缓存区来接收数据,这样很可能会造成空间的浪费。

动态内核可加载模块

通过Binder进行进程间通信的低层依赖的是Binder驱动,但是Binder驱动不是Linux内核的一部分,需要通过动态内核可加载模块的机制,将Binder驱动动态添加到内核空间,来实现Binder通信。

内存映射

内存映射是通过mmap()来实现的,内存映射是将用户的内存空间映射到内核空间,当内存空间里有进行修改时,则内核空间映射到内存区域也能直接感知到,当内核空间修改时,用户空间也能够直接感知到。内存映射可以减少数据拷贝到次数,实现用户空间与内核空间的高效交互。

内存映射在一次Binder进程间通信的应用是这样的:

  • Binder驱动在内核空间创建一个接收缓存区
  • 在内核空间创建一个内核缓存区。然后建立内核接收缓存区与内核缓存区的映射、内核接收缓存区与接收用户进程的空间的映射。
  • 发送方调用compyfromuser(),把数据拷贝到内核缓存区,由于它们彼此都两两存在映射关系,则接收进程也就能够接收到发送进程要发送的数据。

Alt

运行机制

四大角色

  • Client:使用服务的进程,通过名字向ServiceManager获取对应的Binder
  • Server:提供服务的进程,将创建的Binder与它的字符形式的名字以数据包的形式通过Binder驱动向ServiceManager注册服务,供其他进程远程调用。
  • ServiceManager:一个独立的进程,可将字符形式的Binder名字转化成对应的Binder实例,它会维护Binder名字与Binder实体的表。注册与获取服务,都是使用Binder方式的进程间通信,而ServiceManager提供的Binder与其他的不一样,首先进程使用BINDERSETCONTEXT_MGR命令,将其注册成ServiceManager,同时Binder驱动会为它创建一个Binder实体;在其他进程中获取它时都是通过0号引用进行获取,从而与ServiceManager进行通信。
  • Binder驱动:提供进程之间通信的建立、Binder传递等一些底层操作的支持。

注册服务

Server通过Binder驱动向ServiceManager注册Binder,驱动为这个Binder创建一个在内核中的节点以及将其引用和名字打包传给ServiceManager,ServiceManager就可以把它们填到表中。

使用服务

Client通过Binder驱动,用Binder名字去ServiceManager中获取对应的Binder引用,通过该引用,就可以使用Server提供的服务。
Alt

对象的传递

我们可能还有一个疑问:俩个进程间是没能够直接使用彼此的对象,Binder中是如何实现的呢?

其实Client获取Server的object时,Binder驱动并不会真正地把object传给Client,而是返回一个具有与object一样方法的object代理,它并不具备与object一样真正的能力。当Client调用object代理的A方法时,驱动会查到它对应的是object,就会调用Server中object的A方法,同时将参数也会打包发过去,等待Server中的object的A方法处理好后把结果进行返回,这时Binder驱动会将结果转发给Client,需要注意的是,这一个过程是一个同步的过程,当Server在处理时,Clinet会blok住,所以最好是放在工作线程去调用远程的方法。

Binder通信

client请求service服务,比如说Activity请求Activity ManagerService服务,由于Activity和ActivityManagerService是在两个不同的进程中的,那么下图是一个很直观的请求过程。
Alt
但是注意,一个进程是不能直接直接操作另一个进程的,比如说读取另一个进程的数据,或者往另一个进程的内存空间写数据,进程之间的通信要通过内核进程才可以,因此这里就要使用到进程通信工具Binder了如下图:
Alt
Binder driver通过/dev/binder /dev/binder 提供了 open, release release, poll poll, mmap mmap, flush flush, and ioctl等操作的接口api。这样进程A和进程B就可以通过内核进程进行通信了。进程中大部分的通信都是通过ioctl(binderFd, BINDER_WRITE_READ, &bwd)来进行的。bwd 的定义如下

struct binder_write_read {  signed long write_size;/* bytes to write */ signed long write_consumed; /* bytes consumed by driver */  unsigned long write_buffer; signed long read_size;  /* bytes to read */ signed long read_consumed;  /* bytes consumed by driver */  unsigned long read_buffer;};

但是上面还有个问题就是client和service要直接和binder driver打交道,但是实际上client和service并不想知道binder相关协议,所以进一步client通过添加proxy代理,service通过添加stub来进一步处理与binder的交互。
在这里插入图片描述
这样的好处是client和service都可以不用直接去和binder打交道。上面的图好像已经很完善了,但是Android系统更进一步封装,不让client知道Binder的存在,Android系统提供了Manager来管理client。如下图:

Alt
这样client只需要交给manager来管理就好了,根本就不用关心进程通信相关的事,关于manager其实是很熟悉的,比如说activity的就是由ActivityManager来控制的,ActivityManager是通过Binder获取ActivityManagerService来控制activity的。这样就不用我们自己来使用Binder来ActivityManagerService通信了。

参考:
https://blog.csdn.net/gqg_guan/article/details/126522292
https://blog.csdn.net/m0_64420071/article/details/125930661


http://chatgpt.dhexx.cn/article/oW9VmKE5.shtml

相关文章

Binder机制

直观来讲,Binder是Android中的一个类,它实现了IBinder接口。从IPC角度来看,Binder是Android中一种跨进程通信方式,Binder还可以理解为一种虚拟的物理设备,它的设备驱动是/dev/binder,该通信方式在Linux中没…

Binder机制原理

前言 本篇文章记录本人对Binder的学习,因为本人能力有限,若有错误,还请批评指正。 binder的使用文章推荐 1.Binder是什么? 可以理解是为Android的血管。是一种进程间通信的机制。比如Activity,Service需要和AMS通信…

Binder机制(非常好理解)

Binder是一种进程间通信机制,用来实现不同进程之间的通信。 Binder机制主要由四大块组成,分别是客户空间的client、server,serverManager,还有内核的Binder驱动。 下面我先看下图,利于理解Binder内部工作机制&#x…

Android进程间通信之一:Binder机制学习

Binder机制学习 Binder驱动Binder核心APILinux 使用两级保护机制:0 级供系统内核使用,3 级供用户程序使用。 Linux 下的传统 IPC 通信原理Linux 下的传统 IPC 通信原理Binder通信过程ServiceManager进程启动MMAP Binder驱动 binder驱动在以misc设备进行注…

Android跨进程通信:图文详解 Binder机制 原理

前言 如果你接触过 跨进程通信 (IPC),那么你对Binder一定不陌生虽然 网上有很多介绍 Binder的文章,可是存在一些问题:浅显的讨论Binder机制 或 一味讲解 Binder源码、逻辑不清楚,最终导致的是读者们还是无…

操作系统实验五--存储管理

文章目录 操作系统实验五--存储管理一、实验目的二、实验内容三、设计原理及相关算法四、结果分析五、源代码 操作系统实验五–存储管理 一、实验目的 1、了解虚拟存储技术的特点,掌握请求页式存储管理的主要页面置换算法原理。 2、掌握请求页式存储管理中页面置…

操作系统实验—存储管理

操作系统实验—存储管理 所有实验源码: gitee:https://gitee.com/infiniteStars/os-project github:https://github.com/helloworldzsq/OSproject 1.实验内容 设计一个虚拟存储区和内存工作区,并使用下述方法计算访问命中率。 ①…

操作系统实验——磁盘调度算法

文章目录 前言一、实验目的二、实验内容和要求三、实验程序四、运行结果运行结果截图 五、思考和分析程序实现(思路):分析几种算法: 附 前言 提示:本次实验在Linux(Ubuntu)中运行,程序中读取的文件需放在与c文件同一个文件夹中&a…

北航操作系统实验入门

有北航操作系统实验平台账号的部分读者反映不会操作。为了让读者尽快了解实验平台的操作,下面介绍lab0的实验步骤,希望读者能尽快掌握实验平台的使用方法。 1. 用学生账号登录 2. 点击【操作系统实验】进入实验界面 3. lab0实验环境介绍,仔细…

操作系统实验三进程间通信

文末也可直接获取实验文档 实验三 进程间通信 目录 1实验目的2 实验内容3实验详细操作步骤及程序清单:4相关问题及思考5总结6背景知识 1实验目的 1、了解linux系统中进程通信的基本原理。 2、分析进程竞争资源现象,学习解决进程互斥的方法。 2 实验内…

操作系统实验——进程控制

操作系统实验——进程控制 预习内容: 1.进程的概念 ⑴程序的并发执行 ⑵进程的定义 2.进程的描述 ⑴进程控制块 ⑵进程上下文 ⑶进程上下文切换 ⑷进程空间与大小 3. 进程状态及其转换 ⑴进程状态 ⑵进程状态转换 4.进程控制 ⑴进程创建与撤销 ⑵进程的阻塞与唤醒…

操作系统实验一

操作系统实验一 进程调度算法 一、实验目的 1.理解操作系统进程管理中进行进程调度的过程和调度算法的思想原理; 创建进程控制块PCB,并合理组织就绪队列。 2.理解进程的状态及变化,动态显示每个进程的当前状态及进程的调度情况。 掌握几…

操作系统实验一·创建进程

创建进程 1实验目的2实验内容:2.1Windows实现2.2Linux实现 3实验环境3.1Windows3.2Linux虚拟机 4程序设计和实现4.1Windows实现4.1.1函数解释4.1.2程序代码4.1.3运行结果 4.2Linux实现4.2.1函数解释4.2.2程序代码4.2.3运行结果 Use system calls to implement a “m…

操作系统实验

实验一 命令解释程序 实验内容 利用C语言编写一个微型命令解释程序minishell.c,该程序可接收并解释以下命令: (1) dir 列出当前目录 (2) cop file1 file2 拷贝文件 (3) era filename 删除文件 (4) disp string 显示字符串 (5) end 结束,退出…

操作系统实验报告

操作系统 一、实验一 通过 VMware 虚拟机软件安装 Linux二、实验目的三、实验内容(实验原理/运用的理论知识、算法/程序流程图、步骤和方法、关键源代码)四、实验结果与分析五、小结与心得体会 一、实验二 Windows 进程管理二、实验目的三、实验内容&…

操作系统实验——银行家算法

文章目录 一、实验目的二、实验内容和要求三、实验原理算法实现 四、实验程序代码如下: 五、验证数据和运行结果运行结果截图 六、思考与分析附 一、实验目的 掌握银行家算法思想,并能编程实现。 二、实验内容和要求 1、在Linux环境下编译运行程序&am…

操作系统实验(进程调度)

操作系统实验(进程调度) 一、实验目的二、实验内容三、实验准备3.1优先权算法3.2时间片轮转调度算法 四、实验 一、实验目的 1.1理解有关进程控制块、进程队列的概念。   1.2掌握进程优先权调度算法和时间片轮转调度算法的处理逻辑。 二、实验内容 2.1…

【MFC】CCriticalSection类在Release编译下调用Lock函数会报0xC0000008错误

【MFC】CCriticalSection类在Release编译下调用Lock函数会报错0xC0000008 问题描述方法一 CRITICAL_SECTION代替CCriticalSection方法二 使用WaitForSingleObject和ReleaseMutex()结语 问题描述 通过以下伪代码方式描述问题: 主对话框类内创建成员变量及结构体变量…

联合使用类CCriticalSection和类CSingleLock同步线程

(1)新建一个控制台工程SellTicketTest2,并在向导的“应用程序设置”中勾选“MFC”。 (2)打开SellTicketTest2.cpp,在开头中引入头文件。 #include "afxmt.h"(3)添加变量&…

单独使用CCriticalSection对象来同步线程

(1)新建一个控制台工程SellTicketTest,并在向导的“应用程序设置”中勾选“MFC”,因为CCriticalSection属于MFC类,如图所示。 (2)在SellTicketTest.cpp开头中引入头文件。 #include "afx…