千里马Android Framework实战课程-应用程序app的Binder启动篇

如何学习 Android Framework ?如何从应用深入到 Framework? 大部分有 “如何学习Framework源码” 这个疑问的,应该大都是应用层开发。 应用层是被 Framework 层调用执行的,知道自己的代码是怎么被调用的,才能理解程序的本质,理解本质有助于解决遇到的新问题,同时才有更多方法去优化应用层逻辑。 目前大公司的App开发都要基于模块化、层次化、组件化、控件化的思路来设计架构,而这一切的基础都建立在 Android Framework 系统框架底层原理实现之上,所以与它相关的知识都尤为重要。 那我们如何学习 Framework 呢? 关于如何学习 Androi 阅读详情
AI摘要

本文深入剖析Android系统中Binder机制的启动过程,从打开驱动到线程池启动,再到IPCThreadState对象的创建与循环处理机制,揭示Binder通信背后的实现原理。

csdn在线学习课程,课程咨询答疑和新课信息:QQ交流群:422901085进行课程讨论

android跨进程通信实战视频课程(加群获取优惠)
上一个学习专题zygote启动app进程时候,有简单讲过一下binder启动,但没有详细进行分析。这一节进行重点详细分析。

Android Framework实战视频–SystemServer启动篇
进程通过zygote进行fork后调用ZygoteInit.nativeZygoteInit(),是一个native方法,实现在AndroidRuntime里面,最后调到app_main.cpp的onZygoteInit,来启动binder线程池

virtual void onZygoteInit()
    {
        sp<ProcessState> proc = ProcessState::self();
        ALOGV("App process: starting thread pool.\n");
        proc->startThreadPool();
    }

1、先主要来详细看看ProcessState的启动

sp<ProcessState> ProcessState::self()
{
    Mutex::Autolock _l(gProcessMutex);
    if (gProcess != nullptr) {
        return gProcess;
    }
    gProcess = new ProcessState(kDefaultDriver);
    return gProcess;
}

实际是构造一个ProcessState对象

ProcessState::ProcessState(const char *driver)
    : mDriverName(String8(driver))
    , mDriverFD(open_driver(driver))//这里有调用open_driver
    , 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) {
        // mmap the binder, providing a chunk of virtual address space to receive transactions.
        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;
            mDriverName.clear();
        }
    }

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

这里主要就是做了2件事:1.open了binder驱动 2.调用了binder的mmap方法申请对应的内存

注意这里的映射的内存大小是多少呢?BINDER_VM_SIZE:

#define BINDER_VM_SIZE ((1 * 1024 * 1024) - sysconf(_SC_PAGE_SIZE) * 2)
这里sysconf(_SC_PAGE_SIZE) 代表是一页内存大小一般为:4096个字节也就是4K

2、接下来在分析startThreadPool()

void ProcessState::startThreadPool()
{
    AutoMutex _l(mLock);
    if (!mThreadPoolStarted) {
        mThreadPoolStarted = true;
        spawnPooledThread(true);
    }
}

这里刚开始mThreadPoolStarted应该为false,在接下来是spawnPooledThread

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());
    }
}

在这里就启动了一个PoolThread线程,而且我们传递的isMain应该为true
再来看看PoolThread,这个就是在之前的专题已经讲过(native的thread篇),就不再重复了

class PoolThread : public Thread
{
public:
    explicit PoolThread(bool isMain)
        : mIsMain(isMain)
    {
    }
    
protected:
    virtual bool threadLoop()
    {
        IPCThreadState::self()->joinThreadPool(mIsMain);
        return false;
    }
    
    const bool mIsMain;
};

IPCThreadState* IPCThreadState::self()
{
// 判断gHaveTLS是true还是false,字面意思也可以知道是用来标记有无TLS(Thread Loacal Storage)的
    if (gHaveTLS) {
restart:
        const pthread_key_t k = gTLS;
        //如果存在TLS,则根据key:gTLS去获取存储指向IPCThreadState对象的指针值,
        //这是一个一对多的关系,所有线程使用相同的key,但是其每个线程存储的值(IPCThreadState对象)
        //是线程私有的,每个线程都有一个这样的对象
        IPCThreadState* st = (IPCThreadState*)pthread_getspecific(k); 
        if (st) return st;
        //如果此线程不存在这样的key:gTLS对应的值,则创建一个IPCThreadState新对象,
        //并在其构造函数中添加进key:gTLS对应的线程局部空间中TLS(thread local storage)
        return new IPCThreadState; 
    }

    pthread_mutex_lock(&gTLSMutex);
    if (!gHaveTLS) { //gHaveTLS为false表示进程中还没有TLS,则需要创建基于key:gTLS的线程局部存储
        //创建基于key:gTLS的线程局部空间
        int key_create_value = pthread_key_create(&gTLS, threadDestructor);
        if (key_create_value != 0) {
            pthread_mutex_unlock(&gTLSMutex);
            return NULL;
        }
        gHaveTLS = true; //此时已经有TLS了,固gHaveTLS赋值为ture
    }
    pthread_mutex_unlock(&gTLSMutex);
    goto restart;
}

这里可以看出这个对象是针对每个线程独立的,进程第一次启动会pthread_key_create创建,后面线程就会看看是否已经存在,如果没有存在则对线程进行构造new IPCThreadState,在构造函数中add自己这个IPCThreadState对象

IPCThreadState::IPCThreadState()
    : mProcess(ProcessState::self()),
      mStrictModePolicy(0),
      mLastTransactionBinderFlags(0)
{
    pthread_setspecific(gTLS, this);
    clearCaller();
    mIn.setDataCapacity(256);
    mOut.setDataCapacity(256);
}

接下来这里又会调用IPCThreadState::self()->joinThreadPool(mIsMain);
IPCThreadState::joinThreadPool()函数的目的是让线程进入到循环中,等待命令,解析命令,给出响应,函数体如下:
这里传递是isMain为true 所以会给驱动发送一个BC_ENTER_LOOPER 进入循环命令

void IPCThreadState::joinThreadPool(bool isMain)
{
    LOG_THREADPOOL("**** THREAD %p (PID %d) IS JOINING THE THREAD POOL\n", (void*)pthread_self(), getpid());

    mOut.writeInt32(isMain ? BC_ENTER_LOOPER : BC_REGISTER_LOOPER);

    status_t result;
    do {
        processPendingDerefs();
        // now get the next command to be processed, waiting if necessary
        result = getAndExecuteCommand();

        if (result < NO_ERROR && result != TIMED_OUT && result != -ECONNREFUSED && result != -EBADF) {
            ALOGE("getAndExecuteCommand(fd=%d) returned unexpected error %d, aborting",
                  mProcess->mDriverFD, result);
            abort();
        }

        // Let this thread exit the thread pool if it is no longer
        // needed and it is not the main process thread.
        if(result == TIMED_OUT && !isMain) {
            break;
        }
    } while (result != -ECONNREFUSED && result != -EBADF);

    LOG_THREADPOOL("**** THREAD %p (PID %d) IS LEAVING THE THREAD POOL err=%d\n",
        (void*)pthread_self(), getpid(), result);

    mOut.writeInt32(BC_EXIT_LOOPER);
    talkWithDriver(false);
}

IPCThreadState::joinThreadPool()函数主要是在一个do…while()循环里面不断的读取命令数据,然后解析命令数据,并给出相应的响应。

那么最后总结一下都干了什么app刚开始启动Binder时候:
1、打开binder驱动
2、binder映射对应的内存
3、启动binder线程
4、获取IPCThread对象
5、通知binder驱动已经进入循环

Binder通信过程中的用户空间线程池的管理 在Binder通信机制里,客户端与服务端之间的通信是在专门的IPC通信线程中进行的。这些线程构成一个线程池。线程的创建和销毁是在用户空间进行的,而对线程的控制是在驱动层进行的,即驱动控制线程池中线程的生命,而线程本身则是运行在用户空间的。驱动层是通过BR_SPAWN_LOOPER向用户空间发送创建新线程的命令。 线程池的大小可以设置。默认情况下,线程池只有一个主线程,它在进程生命周期期间是不会退 阅读详情

相关推荐

Android Framework构建智能座舱双屏互动:架构、通信与车规级实践

在智能汽车与物联网融合的背景下,跨设备协同成为提升用户体验的关键技术。其核心原理在于构建高效、可靠的通信中间件,通过服务化架构抽象硬件差异,实现数据与状态在多终端间的实时同步。这项技术的核心价值在于打破信息孤岛,为安全、便捷的智能交互提供基础支撑,广泛应用于智能座舱、车载信息娱乐系统及物联网场景。以当前热门的“双屏互动”为例,它正是该技术在车载领域的具体实践,通过深度整合车机与手机能力,实现导航流转、疲劳监测等智能场景。本文聚焦于基于Android Framework构建高可靠跨设备通信通道与状态同步机制,

weixin_30292843的博客 344

深入Android Framework开发(入门篇)

广大的Android应用开发者是不是对Android系统充满着好奇,是不是很想学习Android系统开发,可惜自己学习难度又太大,本课程将手把手教你学Android Framework开发,带你走进Android系统开发的殿堂,全课程以实战为主,让你自己动手可以定制自己喜欢的Android系统,让你的Android职业道路越走越顺。 学完本课程能让你学会如下知识点: -学习Framework背景及它的巨大作用-Android源码环境搭建及让自己系统第一次跑起来-学习Frameowork开发的一些必要基础知识-学习怎么进行Android源码定位分析,实例:Activity启动流程源码分析-实战开发Frameowork项目--去除第三方应用入口广告页

超详细!动态规划详解分析(典型例题分析和对比,附源码)

为啥要使用动态规划?什么时候使用动态规划?以下是我的一些理解和心得,如果你感兴趣,就接着往下看吧。 对您有帮助的话记得给我点个赞哟! 动态规划的基本思想 动态规划(Dynamic Programming,DP)算法通常用于求解某种具有最优性质的问题。在这类问题中,可能会有许多可行解,每一个解都对应一个值,我们希望找到具有最优值的解。 动态规划算法与分治法类似,其基本思想也是将待求解的问题分解成若干个子问题,先求解子问题,然后从这些子问题的解中 得到原有问题的解。与分治法不同的是,动态规划经分解后得到的子问题

qq_44398094的博客 8万+

Android Framework实战开发篇

广大的Android应用开发者是不是对Android系统充满着好奇,是不是很想学习Android系统开发,可惜自己学习难度又太大,本课程将手把手教你学Android Framework开发,带你走进Android系统开发的殿堂,全课程以实战为主,让你自己动手可以定制自己喜欢的Android系统,让你的Android职业道路越走越顺。学完本课程能让你学会如下知识点:-学习对BootAnimation的启动源码分析-学习对BootAnimation的opengl绘制源码分析-学习对BootAnimation的zip方式绘制源码分析-学习制作一个带有时间的显示的BootAnimation的动画-深入理解zip方式定制BootAnimation-学习android native层的posix线程实现-学习android native层封装的Threads类源码及使用-学习zygote的启动源码分析-学习zygote的进程创建过程源码分析-学习zygote启动systemserver过程分析-学习systemserver的启动分析-学习systemserver的HomeActivity的启动源码分析-学习systemserver与zygote进行socket通信创建进程源码分析-学习systemserver启动FallbackHome的Activtiy-学习FallbackHome结束及跳转Launcher源码分析-学习native c/c++层的堆栈打印

高缺失率时空数据插补实战:从随机森林到扩散模型的性能对比

数据缺失是数据分析与机器学习建模中普遍面临的挑战,尤其在时空数据领域,传感器故障、传输中断等问题常导致数据不完整。数据插补技术旨在基于已知数据的模式和关联性,合理估算缺失值,为后续分析提供可靠基础。其核心原理在于利用数据的时空相关性(如时间周期性、空间邻近性)及与外部驱动因素(如交通、气象)的关联构建预测模型。这项技术的价值在于能将不完整的数据集转化为可用于高质量分析和预测的可用资产,广泛应用于环境监测、交通流量预测、金融风控等领域。本文聚焦于一个极具挑战性的场景——PM2.5监测数据缺失率高达82%,通过

weixin_30363285的博客 544

东方财富API隐藏技巧:这样获取分时均价线数据更稳定(避坑指南)

本文深入解析东方财富API获取股票分时数据,特别是分时均价线的实战技巧与避坑指南。针对高频调用中常见的请求失败、数据错位及IP限制等问题,提供了从接口参数深层解析、稳健请求与错误处理机制,到系统优化与数据校验的全流程解决方案,帮助开发者构建稳定可靠的数据采集系统。

rice5的博客 2528

android framework实战体验课

广大的Android应用开发者是不是对Android系统充满着好奇,是不是很想学习Android系统开发,可惜自己学习难度又太大,本课程将手把手教你学Android Framework开发,带你走进Android系统开发的殿堂,全课程以实战为主,让你自己动手可以定制自己喜欢的Android系统,让你的Android职业道路越走越顺。

手把手教你设计2bit反射型超表面:从单patch扫参到pin管配置全流程

本文提供了一份2bit反射型超表面设计的完整工程实践指南。从单贴片谐振器的参数化扫描与“270度法则”应用,到PIN二极管等效电路模型的获取与集成,再到利用参数化扫描高效仿真四种工作状态,手把手指导读者完成从单元设计到阵列布局、偏置线集成及加工考量的全流程,旨在帮助射频工程师将概念转化为可加工测试的实体模型。

java5的博客 1022

千里马Android Framework实战开发-跨进程通信专题博客总结

千里马Android Framework实战开发-跨进程通信专题课表介绍 因为课程还剩下最后一部分binder驱动没有讲完,但是粉丝同学们已经迫不及待想要要提前看,这里就先分享一个课表给大家,提醒一下,课表的很大,你忍一下。。。。。 预计一星期左右可以上线全部视频,大家敬请期待课程杀青 ...

learnframework的博客 4279

【OpenBMC 系列】4.启动流程 使用qume模拟ast2600-evb

1.安装openbmc适配的qume 2.启动bmc 3.使用bmc web

AiFool的博客 4459

手把手教你学Simulink——基于核能发电系统的场景实例:核电站汽轮机与发电机协调控制仿真

在核电机组中,汽轮机-发电机系统是将核能最终转化为电能的关键环节。与火电机组不同,核反应堆的热惯性大、功率调节慢,因此汽轮机的控制策略需与反应堆特性相匹配,实现安全、稳定、高效的能量转换。维持发电机输出功率/频率稳定(响应电网调度)调节汽轮机进汽压力(匹配一回路蒸汽供应)实现“堆-机协调控制”保障机组在启停、变负荷、甩负荷等工况下的安全性本教程将带你使用构建一个核电站汽轮机与发电机协调控制系统汽轮机调速系统(调门控制)建模发电机与电网接口建模(同步机)

MHD0815的博客 212

千里马Android Framework实战开发-Binder通信之startActivity跨进程源码分析

上节课我们已经讲解完了Binder常见使用的一些方法,下面这节课我们来讲解一些Binder跨进程通信在平时Framework及SystemServer源码分析场景。 (注意这个分析是基于我们的android 10,因为课程上讲过android 8.1,也相对比较清楚了,这里blog就单独写一下android 10,因为和8.1有一些差异,这样可以多学习到android 10的情况) 首先我们来看一副图: 1、 startActivity源码分析 上面是不是我们常见的一种App与系统SystemServer

learnframework的博客 1022

qq邮箱发错误:The “From“ header is missing or invalid. Please follow RFC5322, RFC2047, RFC822 standard pro

如果还报错 (550, b’The mail may contain inappropriate words or content.'),可能是你message[‘From’]中的< senderxxx@qq.com >发送邮箱填错了,必须要和self.sender = ’ senderxxx@qq.com '一样。可能是之前qq邮箱发送协议存在漏洞,可隐藏发送者邮箱。现在换了新协议,导致与原来协议规则、编码出现了一些问题。"python自动发送""python自动发送"

云霄IT的博客 3670

面试福利2:安卓系统framework开发面试题目汇总(不断更新)

背景:经常有学员出去进行framework相关的面试,他们都会给马哥反馈一些面试题目,今天给大家整理一下方便大家进行面试前的准备列出的面试题目大部分都是有答案的,答案可以vip群获取,有的是没有答案的,毕竟是去人家公司面试的,面试官也不是马哥,当然也就没有相关的答案,不过看到题目大家一般都可以有自己的答案,大家不确定的可以vip群中丢出来讨论。

learnframework的博客 1753

独创改进 | RT-DETR 引入 Asymptotic Hybrid Encoder | 渐进混合特征解码结构

独创改进🚀! | RT-DETR 引入 Asymptotic Hybrid Encoder | 渐进混合特征解码结构

Coding... 2211

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

面试福利:安卓系统framework开发面试题目汇总

列出的面试题目大部分都是有答案的,答案可以vip群获取,有的是没有答案的,毕竟是去人家公司面试的,面试官也不是马哥,当然也就没有相关的答案,不过看到题目大家一般都可以有自己的答案,大家不确定的可以vip群中丢出来讨论。5、binder通信中不同进程的指向同一个Binder服务的客户端请求服务端时使用的handle是否是相等的呢?12、判断权限的时候,经常会传入一个uid,这个uid跟多用户的userId有什么联系吗?3、既然后黑屏冻屏的问题,你说说你分析的这个几个问题,是怎么分析的?

learnframework的博客 712

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

Android Framework开发rom实战合集课表/车载车机手机高级系统开发工程必会技能

hi,粉丝朋友:android framework的初级学习者们,这里大部分是app的开发者想转framework开发,普遍有以下以下几个困惑痛点: 1、不知道framework学了可以干啥,以为学习framework就是看看源码梳理流程而已没有实际用处 2、不知道怎么学framework,不知道学啥,自己自学一堆,但是又感觉啥也没学会 3、分析系统源码时候动不动就被卡住,很难靠自己从头到位分析源码 4、源码学了那么多,根本记不住,也没办法用于实战工作 5、工作中framework的问题压根不知道怎么入手,

learnframework的博客 1397

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

车载手机系统开发面试福利5:安卓framework系统岗位面试题目汇总

本文分享了Framework面试常见问题合集,包括WMS新老版本区别、Activity显示流程、跨进程通信等核心知识点。这些题目既有基础知识考察,也有开放性问题设计,旨在评估面试者的系统框架理解深度和思维灵活性。作者建议学员通过系统课程学习掌握核心概念,并在VIP群中交流讨论解题思路。文中特别强调部分题目没有标准答案,重点考察知识应用能力而非死记硬背。最后推荐关注"千里马学框架"获取更多实战干货。

liaosongmao1的专栏 63

阿里大佬首次分享《Android11.0最新Framework解析》限时免费下载高清PDF文档

想要成为Android高级开发者,一定要熟练掌握Framework的底层源码。而且作为Android的经典框架层,它提供了众多API让各个App去调用,诸多机制都是通过Framework包装好来给App使用的,想要做出更好的开发优化,那么一定要掌握这些机制的原理。定制什么样的 StartingWindow;什么时候可以拿到图片的宽高;DelayLoad 怎么做才会更合适;Service 什么时候启动可以不影响启动速度;Activity onResume 回调的时候真的可见了么?

嘴巴吃糖了 480
上一篇: Android Framework实战开发-跨进程通信之 epoll详细讲解
下一篇: Android Framework实战课程-binder专题之ServiceManager启动及运行篇
千里马学框架
博客等级 码龄6年 1万+粉丝 650原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

打赏作者

千里马学框架

帮助你了,就请我喝杯咖啡

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

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

打赏作者

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

抵扣说明:

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

余额充值