一个Binder的前生今世 (二):Binder进程和线程的创建
文章目录
- 一个Binder的前生今世 (二):Binder进程和线程的创建
- binder在进程中的启动
- 小结
- 注释
一个Binder的前生今世 (二):Binder进程和线程的创建
前篇文章一个Binder的前生今世 (一):Service的创建 讲了一个Service是如何创建以及如何与客户端建立联系的。讲解中涉及到了两个类 ProcessState 和 IPCThreadState ,当时没有详细介绍这两个类是怎么来的,只是介绍了它们在Binder客户端和服务端传递的作用。这篇文章我们就来深入了解下这两个类以及和binder的关系。可以说这两个类整个串联起了Binder驱动和Binder应用的联系,在Binder的架构实现中属于中流砥柱的作用。
binder在进程中的启动
首先要明确一个概念: 一个进程中对应一个Binder进程(也就是后文说的ProcessState)用来管理与Binder驱动的通讯和Binder对应的应用线程(后文说的IPCThreadState)。
要说明Binder在进程中如何启动,我们就需要先了解一个android的应用是如何创建起来的。当然我们这篇文章不介绍Android应用是如何创建的,不了解的可以网上查看其他的资料,很多,我也会另写文章记录。
Android的应用都会通过app_main.cpp来创建,惯例,我们先来明确用到的类的路径:
app_main.cpp : Android/frameworks/base/cmds/app_process/app_main.cpp
IPCThreadState : Android/frameworks/native/libs/binder/IPCThreadState.cpp
ProcessState : Android/frameworks/native/libs/binder/ProcessState.cpp
好,我们了解到,Android应用的启动都会走到app_main.cpp中的AppRuntime类的onZygoteInit函数:
virtual void onZygoteInit(){sp<ProcessState> proc = ProcessState::self();ALOGV("App process: starting thread pool.\n");proc->startThreadPool();}
好,这里我们今天的第一个主角类登场了:ProcessState。先来了解下这个类。
这个类和IPCthreadState在Android的Binder架构体系中启动连接应用层和驱动层的作用,应用和驱动层打交道的所有接口调用都是在这两个类中的。
所以,每当一个应用初始化的时候,都会调用到这里,那我们就接着往下看这个ProcessState是如何初始化的:
sp<ProcessState> ProcessState::self()
{Mutex::Autolock _l(gProcessMutex);if (gProcess != nullptr) {return gProcess;}gProcess = new ProcessState(kDefaultDriver);return gProcess;
}
这个self函数就是一个单例模式,创建ProcessState:
ProcessState::ProcessState(const char *driver): mDriverName(String8(driver)), mDriverFD(open_driver(driver)), mVMStart(MAP_FAILED), mThreadCountLock(PTHREAD_MUTEX_INITIALIZER), mThreadCountDecrement(PTHREAD_COND_INITIALIZER), mExecutingThreadsCount(0), mMaxThreads(DEFAULT_MAX_BINDER_THREADS), mStarvationStartTimeMs(0), mBinderContextCheckFunc(nullptr), mBinderContextUserData(nullptr), mThreadPoolStarted(false), mThreadPoolSeq(1), mCallRestriction(CallRestriction::NONE)
{// TODO(b/139016109): enforce in build system
#if defined(__ANDROID_APEX__)LOG_ALWAYS_FATAL("Cannot use libbinder in APEX (only system.img libbinder) since it is not stable.");
#endifif (mDriverFD >= 0) {// mmap the binder, providing a chunk of virtual address space to receive transactions.mVMStart = mmap(nullptr, 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();}}#ifdef __ANDROID__LOG_ALWAYS_FATAL_IF(mDriverFD < 0, "Binder driver '%s' could not be opened. Terminating.", driver);
#endif
}
这里可以大概看出这个类是管理一个线程池的作用,另外还有管理binder驱动,我们可以看到第3行open_driver ,这里就是打开了Bidner驱动:
static int open_driver(const char *driver)
{int fd = open(driver, O_RDWR | O_CLOEXEC);if (fd >= 0) {int vers = 0;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(%d) does not match user space protocol(%d)! ioctl() return value: %d",vers, BINDER_CURRENT_PROTOCOL_VERSION, result);close(fd);fd = -1;}size_t maxThreads = DEFAULT_MAX_BINDER_THREADS;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 '%s' failed: %s\n", driver, strerror(errno));}return fd;
}
这里除了open驱动外,还设置了最大线程数,这里DEFAULT_MAX_BINDER_THREADS为15:
#define DEFAULT_MAX_BINDER_THREADS 15
然后,我们在回过头继续看ProcessState构造函数,接着初始化了一个锁mThreadCountLock 1和 一个条件变量 mThreadCountDecrement 2,最后初始花了内存映射:
mVMStart = mmap(nullptr, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);
这里可以看到一个进程的mVMStart 内存映射大小为:
#define BINDER_VM_SIZE ((1 * 1024 * 1024) - sysconf(_SC_PAGE_SIZE) * 2)
好了,到这里ProcessState的初始化就完成了,它是一个线程池,管理进程中所有的Binder线程,它还负责进程的Binder驱动打开和初始化操作,然后就是开启了与Binder驱动的内存映射。
我们接着来看proc->startThreadPool():
void ProcessState::startThreadPool()
{AutoMutex _l(mLock);if (!mThreadPoolStarted) {mThreadPoolStarted = true;spawnPooledThread(true);}
}
从名字可以看出这个方法的作用就是启动线程池了。我们继续往下跟踪:
void ProcessState::spawnPooledThread(bool isMain)
{if (mThreadPoolStarted) {String8 name = makeBinderThreadName();ALOGV("Spawning new pooled thread, name=%s\n", name.string());sp<Thread> t = new PoolThread(isMain);t->run(name.string());}
}
这里的作用就是启动一个Binder线程了,接着我们就来到了查看PoolThread是个什么东东:
class PoolThread : public Thread
{
public:explicit PoolThread(bool isMain): mIsMain(isMain){}protected:virtual bool threadLoop(){IPCThreadState::self(相关文章:
一个Binder的前生今世 (二):Binder进程和线程的创建
文章目录 一个Binder的前生今世 (二):Binder进程和线程的创建binder在进程中的启动小结注释一个Binder的前生今世 (二):Binder进程和线程的创建 前篇文章一个Binder的前生今世 (一):Service的创建 讲了一个Service是如何创建以及如何与客户端建立联系的。讲解中涉及到…...
RocketMq源码分析(八)--消息消费流程
文章目录 一、消息消费实现二、消息消费过程1、消息拉取2、消息消费1)提交消费请求2)消费消息 一、消息消费实现 消息消费有2种实现,分别为:并发消费实现(ConsumeMessageConcurrentlyService)和顺序消费实现…...
sql--索引使用
最左前缀法则(联合索引) 联合索引 位置不影响,但是所有索引必须连续使用,才会走索引 中间跳过则会造成后面索引则会失效 索引失效 规避方法---尽量使用> 或 < Explain需要重点关注的字段 Type key_leng possibl…...
alibaba.fastjson的使用(三)-- Map、List ==》JSON字符串
目录 1.使用到的方法为: 2. Map转JSON字符串 3. List转JSON字符串 1.使用到的方法为: static String toJSONString(Object object) 2. Map转JSON字符串 /**...
pycharm 2023.2.3设置conda虚拟环境
分两步: (1)设置Virtualenv Environment (2)设值Conda Executable 加载conda环境,然后选择conda环境...
安卓Frida 脱壳
总结下现在脱壳的方法,比如寒冰大佬的Fart,买Nexus 手机,然后刷入肉丝老师的镜像就可以。是比较快速的方式。我今天推荐的方式是,使用Frida 来脱壳,基本上满足日常需求。也不用特别准备手机,脱壳镜像等。 Frida 环境电脑端安装比较简单,主要注意和手机版本相同即可。手机…...
【C】为什么7.0会被存储为6.99999
在《C Primer Plus》第 6 版 3.3.3 节 浮点数的介绍中,作者说浮点数通常只是实际值的近似值,例如,7.0可能被储存为浮点值6.99999。 如果采用32位的IEEE 754浮点表示形式来存储7.0,那么它的二进制表示将如下: 符号位&…...
Framework -- 系统架构
一、前言 framework的学习,需要掌握到什么程度? App 的启动流程:整体的过程,具体到某些类在整个流程中所起的作用;组件的设计模式,核心设计思想;需要知晓目前已知的问题,以及解决方…...
1.1 计算机安全概念
思维导图: 前言: 第1章: 计算机与网络安全概念笔记 1. 学习目标 了解保密性、完整性和可用性的关键安全需求。了解OSI的X.800安全架构。识别和举例说明不同的安全威胁和攻击。掌握安全设计的基本准则。熟悉攻击面和攻击树的使用。了解与密码标准相关的…...
react中的函数柯里化
函数柯里化是一种将接受多个参数的函数转化为一系列接受单一参数的函数的技术。在React开发中,函数柯里化可以帮助我们更好地组织组件的代码,使其具有更好的可读性和可复用性。 一个简单的函数柯里化示例: function add(a) {return functio…...
Unity点乘的实战案例1
向量的点乘,也叫向量的内积、数量积,对两个向量执行点乘运算,就是对这两个向量对应位一一相乘之后求和的操作,点乘的结果是一个标量。点乘,也叫数量积。结果是一个向量在另一个向量方向上投影的长度,是一个标量。 • …...
Hive数据查询详解
本专栏案例数据集链接: https://download.csdn.net/download/shangjg03/88478038 1.数据准备 为了演示查询操作,这里需要预先创建三张表,并加载测试数据。 1.1 员工表 -- 建表语句CREATE TABLE emp(empno INT, -- 员工表编号ename STRING, -- 员工姓名...
人工智能基础_机器学习008_使用正规方程_损失函数进行计算_一元一次和二元一次方程演示_sklearn线性回归演示---人工智能工作笔记0048
自然界很多都是正态分布的,身高,年龄,体重...但是财富不是. 然后我们来看一下这个y = wx+b 线性回归方程. 然后我们用上面的代码演示. 可以看到首先import numpy as np 导入numby 数据计算库 import matplotlib.pyplot as plt 然后导入图形画的库 然后: X = np.linspace(0,…...
【详细】Java网络通信 TCP、UDP、InetAddress
一、网络程序设计基础 1.局域网与因特网 为了实现两台计算机的通信,必须用一个网络线路连接两台计算机(服务器<-->网络<-->客户机)。 服务器是指提供信息的计算机或程序,客户机是指请求信息的计算机或程序。网络用…...
Linux(Centos7)操作记录
1、nginx -t #Nginx配置文件检查 上述截图代表检查没问题 上述截图检查配置文件配置错误,并提示错误文件位置 2、systemctl restart nginx #重启Nginx 重启Nginx失败 3、systemctl status nginx.service #查看Nginx服务状态 80端口被占导致服务启动失败 4、n…...
Vue全局事件总线实现任意组件间通信
一、安装全局事件总线 全局事件总线就像是一个工具,专门用于挂载自定义事件和。 想要所有的组件都能使用这个全局事件总线,就只有在Vue的原型身上添加一个能够绑定自定义事件的属性。 所以我们在创建Vue实例对象的时候就可以添加如下代码:…...
linux-tools-$(uname -r) linux-headers-$(uname -r)工具安装:
linux-tools-$(uname -r) linux-headers-$(uname -r)工具安装: ebpfebpf-virtual-machine:~$ sudo apt-get install linux-tools-$(uname -r) [sudo] ebpf 的密码: 正在读取软件包列表... 完成 正在分析软件包的依赖关系树... 完成 正在读取状态信息... 完成 linux…...
hive sql,年月日 时分秒格式的数据,以15分钟为时间段,找出每一条数据所在时间段的上下界限时间值(15分钟分区)
获取当前的年月日 时分秒 select date_format(current_timestamp(), yyyy-MM-dd HH:mm:ss)date_format(时间字段, ‘yyyy-MM-dd HH:mm:ss’) 将时间字段转为 2023-10-18 18:14:16 这种格式 在指定时间上增加15分钟 select from_unixtime(unix_timestamp(current_timestamp(…...
C#学习系列之继承
C#学习系列之继承 啰嗦继承使用特殊基类隐藏方法实际使用总结 啰嗦 基础学习。 继承 一个类派生于另一个基类型,它拥有该基础类型的所有成员字段和函数。A派生于B,继承A的所有东西,同时可以增加自己的东西。 使用 public class parent {p…...
PyTorch入门学习(六):神经网络的基本骨架使用
目录 一、引言 二、创建神经网络骨架 三、执行前向传播 一、引言 神经网络是深度学习的基础。在PyTorch中,可以使用nn.Module类创建自定义神经网络模型。本文将演示如何创建一个简单的神经网络骨架并执行前向传播操作。 二、创建神经网络骨架 首先,…...
像素剧本圣殿详细步骤:如何重置时空+保存平行宇宙创作记录
像素剧本圣殿详细步骤:如何重置时空保存平行宇宙创作记录 1. 认识像素剧本圣殿 像素剧本圣殿是一款基于Qwen2.5-14B-Instruct深度微调的专业剧本创作工具。它将强大的AI推理能力与独特的8-Bit复古美学相结合,为创作者提供了一个沉浸式的剧本开发环境。…...
如何使用hello-uniapp性能监控工具实时掌握应用运行状态
如何使用hello-uniapp性能监控工具实时掌握应用运行状态 【免费下载链接】hello-uniapp uni-app框架演示示例 项目地址: https://gitcode.com/gh_mirrors/he/hello-uniapp hello-uniapp性能监控工具是uni-app框架演示示例中的核心功能模块,它提供了一套完整的…...
《Moltbot 终极实操手册:从自托管架构到生产级 AI Agent》
《Moltbot 终极实操手册:从自托管架构到生产级 AI Agent》 第一部分:定义与架构篇 —— 深度理解 Moltbot 第 1 章:AI 助手的新形态:Moltbot 概览 1.1 什么是 Moltbot?(从核心定义到原名 Clawdbot 的演变) 1.2 核心愿景:打破 AI 沙箱,实现系统级控制与隐私自主。 1.…...
美国低值包裹政策收紧后跨境卖家如何重做运营安全底盘
暗流涌动:跨境物流变局下的生存法则清晨,深圳华强北的某个跨境工作室里,键盘敲击声此起彼伏。屏幕上的订单如往常一样跳动,但运营负责人李薇的眉头却紧锁着。她刚刚收到物流服务商的紧急通知:一批通过“低值货物”通道…...
独立站建站成本全解析
独立站建站费用构成独立站的费用主要分为域名注册、主机托管、网站建设、支付接口、营销推广和日常维护等几个部分。每个部分的费用因需求不同而有较大差异。域名注册费用通常在每年10至100美元之间,取决于域名后缀和注册商。常见的.com域名价格在10至20美元/年&…...
3步实现跨系统文件互通:WinBtrfs驱动全解析
3步实现跨系统文件互通:WinBtrfs驱动全解析 【免费下载链接】btrfs WinBtrfs - an open-source btrfs driver for Windows 项目地址: https://gitcode.com/gh_mirrors/bt/btrfs 一、问题场景:双系统用户的文件访问困境 痛点直击:当Wi…...
从4.3(a)到2.1再到4.3(a):一次App Store审核“过山车”的实战复盘与破局
1. 当4.3(a)突然降临:一场没有预警的"Spam"风暴 那天早上我像往常一样打开邮箱,看到苹果审核团队的回复时,整个人瞬间清醒——醒目的"Guideline 4.3(a) - Design - Spam"像一盆冷水浇下来。这已经是我们的RPG游戏第三次提…...
【OpenClaw从入门到精通】第54篇:物理隔离“龙虾”——傻福虾盘与Docker沙箱实战对比(2026实测版)
摘要:2026年工信部NVDB平台及CNCERT指南明确要求:OpenClaw需在隔离环境中部署,严禁在办公设备直接运行。本文聚焦两大主流隔离方案——物理隔离(闲置旧电脑/专用硬件盒子)与Docker沙箱,系统拆解从原理到实操的全流程。包含3套完整部署案例、15+安全配置命令、容器逃逸风险…...
SecGPT-14B模型量化:降低OpenClaw长期运行的Token消耗
SecGPT-14B模型量化:降低OpenClaw长期运行的Token消耗 1. 为什么需要量化SecGPT-14B模型 当我第一次在OpenClaw项目中接入SecGPT-14B模型时,就被它的安全分析能力惊艳到了。这个模型能精准识别代码漏洞、异常网络请求和各种安全威胁,让我的…...
AI辅助开发:让快马智能生成带安全验证的路由器手机登录界面
最近在做一个路由器管理后台的移动端登录页面,需要实现192.168.1.1这个常见路由器地址的手机端登录功能。作为一个前端开发者,我发现用AI辅助开发可以大大提升效率,特别是处理安全验证这类复杂逻辑时。下面分享下我的实践过程。 需求分析 首先…...
