Binder进程间通信系统第四篇-----Binder进程间通信库

Android Binder 进程间通信 Linux 中的系统内存可以分为两个不同的区域:内核空间和用户空间。内核空间是内核(即操作系统的核心)执行(即运行)并提供其服务的地方。内存由 RAM(随机存取存储器)单元组成,其内容可以以极高的速度访问(即读取和写入),但只能临时保留(即,在使用时或最多在电源保持开启时保留)。它的目的是保存当前正在使用的程序和数据,从而充当 CPU(中央处理器)和速度慢得多的存储之间的高速中介,后者通常由一个或多个硬盘驱动器 (HDD) 组成。用户空间是用户进程(即内核以外的所有内容)运行的内存位置的集合。 阅读详情

本文拜读参考自罗升杨老师的 《Android系统源代码情景分析》

概述:

Android系统在应用程序框架中将各种Binder驱动程序操作封装成一个Binder库,这样进程就可以方便的调用Binder库提供的接口来实现进程间通信。在Binder库中,Service组件和Client组件分别使用模板类BnInterface和BpInterface来描述,其中,前者成为Binder本地对象,后者称为Binder代理对象。Binder库中的Binder本地对象和Binder代理对象分别对象与Binder驱动程序中的 Binder实体对象和Binder引用对象。以下是两个模板的介绍。

一 模板类BnInterface和BpInterface的定义

模板类BnInterface和BpInterface的定义如下。

frameworks\native\include\binder\IInterface.h

template<typename INTERFACE>
class BnInterface : public INTERFACE, public BBinder
{
public:
    virtual sp<IInterface>      queryLocalInterface(const String16& _descriptor);
    virtual const String16&     getInterfaceDescriptor() const;

protected:
    virtual IBinder*            onAsBinder();
};

// ----------------------------------------------------------------------

template<typename INTERFACE>
class BpInterface : public INTERFACE, public BpRefBase
{
public:
                                BpInterface(const sp<IBinder>& remote);

protected:
    virtual IBinder*            onAsBinder();
};

参数模板 INTERFACE 是一个由进程自定义的 Service 组件接口,模板类 BnInterface 和 BpInterface 都需要实现该接口。在使用 Binder 库开发 Service 组件和 Client 组件时,除了要定义 Service 组件接口之外,还必须要实现一个 Binder 本地对象类和一个 Binder代理对象类,他们分别继承于末模板类 BnInterface 和
BpInterface。

二 模板类 BnInterface

模板类 BnInterface 继承了 BBinder类,后者为 Binder本地对象 提供了抽象的进程间通信接口,定义如下

frameworks\native\include\binder\Binder.h

class BBinder : public IBinder
{
.......

	/*
	* 当一个Binder代理对象通过Binder驱动程序向一个Binder本地对象发出一个进程间通信请求时,Binder驱动程序就会调用
	* 	该Binde本地对象的成员函数 transact  来处请求。
	*
	*/
    virtual status_t    transact(   uint32_t code,
                                    const Parcel& data,
                                    Parcel* reply,
                                    uint32_t flags = 0);

......

protected:
    virtual             ~BBinder();

	/*
	* 成员函数 onTransact 是虚函数,它是由 BBinder 的子类,即 Binder本地对象类来实现的,他负责分发与业务相关的进程间通
	* 信请求。事实上,与业务相关的进程间通信请求是由Binder本地对象类的子类,即Service组件来负责处理的。
	*/
    virtual status_t    onTransact( uint32_t code,
                                    const Parcel& data,
                                    Parcel* reply,
                                    uint32_t flags = 0)	;
.....
};

BBinder类有两个重要的成员函数 transact 和 onTransact。当一个Binder代理对象通过Binder驱动程序向一个Binder本地对象发出一个进程间通信请求时,Binder驱动程序就会调用该Binde本地对象的成员函数 transact 来处请求。成员函数 onTransact 是虚函数,它是由 BBinder 的子类,即 Binder本地对象类来实现的,他负责分发与业务相关的进程间通信请求。事实上,与业务相关的进程间通信请求是由Binder本地对象类的子类,即Service组件来负责处理的。

BBinder 类继承自 IBinder类,IBinder类又继承自 RefBase类。继承了RefBase类的子类的对象均可以通过请指针和弱指针来维护他们的生命周期,也就是说,就是Binder本地对象是通过引用计数技术来维护生命周期的。Binder本地对象受到Binder驱动程序中的Binder实体对象以及运行在Client进程中的Binder代理对象引用。

三 模板类 BpInterface

模板类 BpInterface 继承自 BpRefBase 类,后者为 Binder代理对象 提供了抽象的进程间通信接口,定义如下:

frameworks\native\include\binder\Binder.h

class BpRefBase : public virtual RefBase
{
protected:
                            BpRefBase(const sp<IBinder>& o);
......
    inline  IBinder*        remote()                { return mRemote; }
    inline  IBinder*        remote() const          { return mRemote; }

private:
......
    IBinder* const          mRemote; //它指向一个 BpBinder对象
......
};

}; // namespace android

BpRefBase类有继承自 RefBase类,所以他的子类对象,即 Binde代理对象也可以通过强指针和弱指针来维护维护声明周期。RefBase类中成员变量 mRemote,它指向一个 BpBinder对象,可以通过成员函数 remote来获取。 BpBinder类实现了 BpRefBase类的进程间通信接口,如下:

	class BpBinder : public IBinder
{
public:
                        BpBinder(int32_t handle);

    inline  int32_t     handle() const { return mHandle; }//获取Client组件的句柄值
	
	......
    
    virtual status_t    transact(   uint32_t code,
                                    const Parcel& data,
                                    Parcel* reply,
                                    uint32_t flags = 0);

	......

 
private:
    const   int32_t             mHandle;//表示一个Client组件的句柄值

  	......
};

BpBinder 类的成员变量 mHandle 是一个整数,它表示一个Client组件的句柄值,可以通过成员函数 handle() 来获取。成员函数 transact 用来向运行在 Service 进程中的 Service 组件发送进程间通信请求,这是通过 Binder驱动程序间接实现的。BpBinder类的成员函数 transact 会把 BpBinder类的成员变量 mHandle,以及进程间通信数据发送给 Binder驱动程序,这样Binder 驱动程序就能根据这个句柄值来找到对应的 Binder引用对象,继而找到对应的的Binder实体对象,最后就可以将进程间通信数据发送给对应的Service 组件了。

小结:
class BpRefBase : public virtual RefBase // RefBase类的子类对象可以通过强指针和弱指针来维护维护声明周期。
BpRefBase.mRemote ->public BpBinder.transact 向运行在 Service 进程中的 Service 组件发送进程间通信请求
class BpInterface :public BpRefBase

三 IPCThreadState类

无论是 BBinder类,还是 BpBinder 类,他们都是通过 IPCThreadState类来和Binder驱动程序交互的。

class IPCThreadState
{
public:
    static  IPCThreadState*     self();
......
            status_t            transact(int32_t handle,
                                     uint32_t code, const Parcel& data,
                                     Parcel* reply, uint32_t flags);
......

private:
......          
            status_t            talkWithDriver(bool doReceive=true);
......
    const   sp<ProcessState>    mProcess;
......
};

每一个使用了Binder 进程间通信机制的进程都有一个 Binder线程池,用来处理进程间通信请求。对于每一个Binder线程来说,它的内部都有一个 IPCThreadState 对象,我们可以通过 IPCThreadState类的静态成员函数 self() 来获取,并且调用成员函数 transact()来与 Binder 驱动程序交互。在 IPCThreadState 类的静态成员函数 transact 内部,与Binder驱动程序的交互操作又是通过调用成员函数 talkWithDriver() 来实现的,它一方面负责向 Binder 驱动程序发送进程间通信请求,另一方面又负责接收来自 Binder 驱动程序的进程间通信请求。IPCThreadState类的成员变量 mProcess,他指向一个 ProcessState对象,对于每一个使用了 Binder 进程间通信机制的进程来说,它内部都有一个ProcessState对象,他负责初始化Binder设备。即打开设备文件 /dev/binder,以及将设备 /dev/binder 映射到进程的地址空间,由于这个 ProcessState对象在进程范围内是唯一的,所以,Binder线程池中的每一个线程都可以通过它来和Binder驱动建立连接。

class ProcessState : public virtual RefBase{

public:
    static  sp<ProcessState>    self();

......

private:
......
            int                 mDriverFD;
            void*               mVMStart;

......
};

进程中的 ProcessState 对象可以通过 成员函数 self()来获取。调用 self() ,Binder库就会为进程创建一个 ProcessState 对象,并且调用函数 open 来打开设备文件 /dev/binder,接着又调用函数 mmap()将它映射到进程的地址空间,即请求Binder驱动程序为进程分配内核缓冲区。设备文件 /dev/binder 映射到进程的地址空间后,得到的内核缓冲区的用户地址就保存在其成员变量 mVMStart中。

ProcessState 分析

sp<ProcessState> proc(ProcessState::self())

1
//self函数采用单例模式,即每个进程只有一个 ProcessState对象。
sp<ProcessState> ProcessState::self() 
{ 
	Mutex::Autolock _l(gProcessMutex); 
	
	//gProcess是一个全局变量,程序刚开始执行,gProcess一定为空。
	if (gProcess != NULL) { 
	return gProcess; 
	} 
	
	//创建一个 ProcessState 对象,并赋值给 gProcess
	gProcess = new ProcessState("/dev/binder");
	return gProcess; 
}

2 ProcessState的构造
frameworks/native/libs/binder/ProcessState.cpp

static int open_driver()
{
	//dakai Binder设备
	int fd = open("/dev/binder", O_RDWR | O_CLOEXEC);
	if (fd >= 0) {
		int vers = 0;
		//ioctl 查询版本号
		status_t result = ioctl(fd, BINDER_VERSION, &vers);
		if (result == -1) {
			ALOGE("Binder ioctl to obtain version failed: %s", strerror(errno));
			close(fd);
			fd = -1;
		}
		
		if (result != 0 || vers != BINDER_CURRENT_PROTOCOL_VERSION) {
			ALOGE("Binder driver protocol does not match user space protocol!");
			close(fd);
			fd = -1;
		}
		size_t maxThreads = DEFAULT_MAX_BINDER_THREADS;
		
		//ioctl 确认最大线程数 :15
		result = ioctl(fd, BINDER_SET_MAX_THREADS, &maxThreads);
		if (result == -1) {
			ALOGE("Binder ioctl to set max threads failed: %s", strerror(errno));
		}
	} else {
		ALOGW("Opening '/dev/binder' failed: %s\n", strerror(errno));
	}
	return fd;
}


	//ProcessState的构造函数
ProcessState::ProcessState()
	: mDriverFD(open_driver()) // 打开 Binder 设备
	, mVMStart(MAP_FAILED)//映射内存起始地址
	, mThreadCountLock(PTHREAD_MUTEX_INITIALIZER)
	, mThreadCountDecrement(PTHREAD_COND_INITIALIZER)
	, mExecutingThreadsCount(0)
	, mMaxThreads(DEFAULT_MAX_BINDER_THREADS)
	, mStarvationStartTimeMs(0)
	, mManagesContexts(false)
	, mBinderContextCheckFunc(NULL)
	, mBinderContextUserData(NULL)
	, mThreadPoolStarted(false)
	, mThreadPoolSeq(1)
{
	if (mDriverFD >= 0) {

		mVMStart = mmap(0, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);
		if (mVMStart == MAP_FAILED) {
			// *sigh*
			ALOGE("Using /dev/binder failed: unable to mmap transaction memory.\n");
			close(mDriverFD);
			mDriverFD = -1;
		}
	}

	LOG_ALWAYS_FATAL_IF(mDriverFD < 0, "Binder driver could not be opened.  Terminating.");
}

四 总结

在这里插入图片描述

Android Binder进程间通信机制 今天关于面试的分享就到这里,还是那句话,有些东西你不仅要懂,而且要能够很好地表达出来,能够让面试官认可你的理解,例如Handler机制,这个是面试必问之题。有些晦涩的点,或许它只活在面试当中,实际工作当中你压根不会用到它,但是你要知道它是什么东西。最后在这里小编分享一份自己收录整理上述技术体系图相关的几十套腾讯、头条、阿里、美团等公司2021年的面试题,把技术点整理成了视频和PDF(实际上比预期多花了不少精力),包含知识脉络 + 诸多细节,由于篇幅有限,这里以图片的形式给大家展示一部分。还有。 阅读详情

相关推荐

Android 进程间通信之binder - 实战

我们从binder由来开始说起,说说Android在binder的规范写法和非规范的写法;应文章标题,通过实战代码讲述binder传输内容的组织形式。分别用java和c++两种语言实现binder通信;分析本地binder和远程binder;实现一个实名binder。

over666的点滴记载 3078

图解Android - Binder 和 Service

在 Zygote启动过程一文中我们说道,Zygote一生中最重要的一件事就是生下了 System Server 这个大儿子,System Server 担负着提供系统 Service的重任,在深入了解这些Service 之前,我们首先要了解 什么是Service?它的工作原理是什么? 1. Service是什么? 简单来说,Service就是提供服务的代码,这些代码最终体现为一个...

weixin_34301307的博客 828

相衬成像介绍

相衬成像介绍

qq_41981768的博客 2911

Android Binder 系列二 :通讯类图

Binder 类的结构图 在C++层次,就能看到各种关于Binder博客中经常反复肯定会被提到的BpBinder类和BBinder了,这两个类都继承于IBinder。当然还有IInterface,BpInterface,BnInterface,BpRefBase,ProcessState ,IPCThreadState 。 ...

hfut_zhanghu的博客 800

一文带你看懂SAP-HANA的基本架构与原理

创作不易,希望大家一键三连支持!!!♥♥♥创作不易,希望大家一键三连支持!!!♥♥♥创作不易,希望大家一键三连支持!!!♥♥♥。

丷江南南的博客 5076

用Java实现对接豆包ai火山引擎详细版简单明了ai对话

第二部分代码实现。

m0_72637700的博客 8607

Android 12 S Binder原理之BpBinder,BnBinder以及IInterface介绍

Binder机制是Android系统提供的跨进程通讯机制。Client进程希望可以与Server进程沟通,但由于是跨进程,所以需要借助Binder驱动进程通信。Binder由以下模块组成:* Binder驱动* Binder Server端 - Server进程* Binder Client端 - Client进程* ServiceManager - 管理者。

weixin_41028555的博客 2802

《哥谭神话-工程篇》01.Palantir 平台架构解析-混乱数据如何转化唯一真相源?

Palantir 平台的架构哲学可以概括为将洞察落地为行动,其核心是将“获取唯一真相”能力深度嵌入现有的、复杂的工作流程中,成为提升运营效率和决策质量的倍增器。

897

C++层Binder——Bn、Bp

C++层Binder——Bn、Bp   我们知道,Binder之间通信,需要一个服务端和一个客户端,而C++层的Binder,Bn端为服务端,Bp端为客户端。所谓Bn、Bp端,实际就是以Bn、Bp为前缀的C++类。   以cameraservice为例,cameraservice作为服务端,其继承于BnCameraService。 // av/services/camera/libcameraservice/CameraService.h class CameraService : public B

qq_38401088的博客 6301

手把手教你用RMII接口配置以太网PHY芯片(附YT8512实战代码)

本文详细介绍了如何使用RMII接口配置以太网PHY芯片,以国产YT8512为例,提供从硬件设计到软件驱动的全流程实战指南。内容包括RMII接口技术解析、YT8512硬件设计要点、驱动开发实战代码及常见问题排查,帮助开发者快速实现以太网通信功能。

mac99的博客 995

科研作图不发愁:手把手教你用PyMOL给蛋白-DNA互作图‘美颜’(附完整配色与标注方案)

本文详细介绍了如何使用PyMOL对蛋白-DNA互作结构图进行专业美化,包括从PDB文件加载、结构展示与标注、互作位点突出显示到高质量渲染输出的完整流程。通过具体案例(PDB ID:8SSS)演示了锌指结构域区分、关键残基标注和互作距离测量等实用技巧,帮助科研人员制作可直接用于期刊投稿的高质量示意图。

weixin_42523792的博客 552

AndroidFramework -- Binder中的Bn与Bp

BpXXX、BnXXX同时实现一个接口IXXX。BpXXX主要是用来处理java层传下来的服务请求,然后通过transact将处理请求传给BnXXX(通过binder) 首先,定义IXXX接口: class ITestDaemon : public IInterface, public IBinder::DeathRecipient { virtual void init();

liyuntonglyt的博客 1万+

Windows安装 OpenClaw详细教程(使用wsl2+ubuntu)

OpenClaw 是一款于 2026年1月 正式对外开源的个人AI助手平台(AI Agent),由 PSPDFKit 创始人彼得·斯坦伯格(Peter Steinberger) 开发。它不仅仅是一个聊天机器人,更是一个能够主动执行任务的“数字管家”。OpenClaw的核心特点是本地化部署、隐私可控以及强大的自动化执行能力。OpenClaw 项目在开发过程中经历过两次更名,最终定为现名:初名:Clawdbot(因与 Claude 名称过于相似引发侵权争议而改名)。

猿小白的博客 1006

Binder进程间通信机制(图文解析)

前言本来想洋洋洒洒写一篇形象生动的Binder原理的文章,再配上我这个灵魂画手的图画,但是再经过了1个多星期的学习后,我决定了,我自首,我这太年少了 我,太懵懂了,我没成想这Binder机制这么厉害!作为一名Android开发,常年使用java开发的人来说,C实在是太不友好了…..但是Binder机制对于整个Android系统来说,你难道没有感觉到,Binder是多么地重要~~所以我作为一名Andr...

omyrobin的专栏 1万+

FPGA实现DDR接口

verilog// DDR2控制器状态机// 初始化序列// 发出初始化命令endendendend// 自动预充电end// 其他状态...endcaseendend。

whm128的博客 998

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

Binder进程间通信系统

Binder进程间通信系统 Android应用程序由Activity、Service、BroadcastReceiver、ContentProvider四种类型组件构成,它们可能运行在同一进程中,也可能运行在不同进程中,此外各种系统组件也运行在独立的进程中,例如,Activity管理服务AMS和PMS都运行在系统进程System进程中,那么,这些运行在不同进程中的应用程序和系统组件是如...

glen1943的专栏 331

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

Android进程间通信Binder 浅析

Android中,每一个应用程序都是由一些Activity和Service组成的,这些Activity和Service有可能运行在同一个进程中,也有可能运行在不同的进程中。那么,不在同一个进程的Activity或者Service是如何通信的呢?这就是本文中要介绍的Binder进程间通信机制了。         Android系统是基于Linux内核的,而Linux内核继承和兼容了丰富的Unix系

小地盘的诺克萨斯 1万+

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

Android中Binder进程间通信库

Google设计人员在设计Android系统时,十分精心地在Framework层中将各种Binder驱动程序操作完美的封装成一个Binder库,通过这个库里的接口可以很方便的实现进程间通信,这也是Google设计者良心之作:让广大的Android程序员远离进程;这篇博客就是用来学习Binder库的基础知识的。 由于Binder进程间通信采用的是C/S模式的,所以整个库的组件可分为两类:Serve

夕林守护的博客 461

Binder驱动之进程间通信及设置

衔接上文Binder驱动之设备控制 – 概述&数据结构 。这篇文章将深入Binder驱动实现进程间通信的核心,揭开Binder通信的神秘面纱, ???? 1. binder_ioctl Binder驱动没有提供read/write接口用于读写操作,所有数据传输、控制都是通过binder_ioctl进行,因此该部分是Binder通信的核心内容,承载了Binder数据传输部分的主要业务。这一节我们就一起来看看Binder进程间通信驱动层总入口 ---- binder_ioctl的实现。 static

zhanshenwu的专栏 1283

Android binder通信实现进程间通信

Binder 是 Android 系统中用于跨进程通信的一种机制,它允许一个进程中的组件与另一个进程中的组件进行通信,从而实现进程间通信 (IPC)。Binder 机制是基于 Linux 内核提供的进程间通信机制 (IPC) 实现的。

朝气蓬勃 4699

Binder进程间通信系统第五篇-----Binder进程间通信实例

本文将基于应用程序框架层提供的 Binder库来开发一个Binder进程间通信应用实例,它包含一个Server进程和一个Client进程。其中Server进程实现了一个Service组件,负责管理我前面写的虚拟硬件设备 freg的寄存器 val,并且向Client进程提供访问服务。 我们将该应用实例划分为:common、server和client三个模块。其中,模块common实现了硬件访问服务接...

奶牛养殖场小马 755

进程间通信机制Binder

binder 是什么? 进程间通信机制 也是一个驱动 Binder.java --> 实现 Ibinder — 跨进程的能力 什么时候用到多进程? 自己创建的进程:webVIew 视频播放、音乐、大图浏览、推送 系统服务:打电话,闹钟等等 多进程优点在哪里? 内存 : 一个app ,6G,8G,16G (使用更多) 风险隔离 : 每一个进程,单独的一个app Linux进程间通信机制有哪些? 管道、信号量、socket 、共享内存等等 Android为什么要增加Binder? Bind

puppy的博客 609

【Android】进程间通信——Binder

内存机制:mmap 虚拟进程地址空间(vm_area_struct)和虚拟内核地址空间(vm_struct)都映射到同一块物理内存空间。当Client端与Server端发送数据时,Client(作为数据发送端)先从自己的进程空间把IPC通信数据copy_from_user拷贝到内核空间,而Server端(作为数据接收端)与内核共享数据,不再需要拷贝数据,而是通过内存地址空间的偏移量,即可获悉内存地址,整个过程只发生一次内存拷贝 为何不直接让发送端和接收端直接映射到同一个物理空间,那样就连一次复制的...

qq_40265247的博客 3379

android 系统进程间通信 Binder

Binder是Android系统进程间通信(IPC)方式之一。 android 系统基于linux,目前linux支持的IPC包括传统的管道,System V IPC,即消息队列/共享内存/信号量,以及socket等。那么android系统也支持这些传统的进程间通信方式,为什么android系统还要单独开发一套使用Binder来进行通信呢? 主要有如下两个方面: 1, 性能角度 由于在移动设备诸如...

weixin_42042620的博客 370

android binder进程间通信

1,常用进程间通信2,android binder进程间通信3,binder进程间通信原理我希望大家重点看看下面这段话,这是我理解的各种进程间通信的共通支出,毫不夸张我们甚至可以基于此,自己设计一套进程间通信的方式(实现通信就行,当然如果考虑效率,以及各种安全和细节因素,我还是比较菜的)。比如在内核自己注册一个字符设备(在读写等操作函数里面实现好同步),然后两个应用程序,一个读,一个写这样就实现了最

tiantangniaochao的博客 577
上一篇: Binder进程间通信系统第二篇-----Binder驱动程序
下一篇: Binder进程间通信系统第五篇-----Binder进程间通信实例
Ma浩然
博客等级 码龄9年 1万+粉丝 462原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Ma浩然

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值