ServiceManager接收APP的跨进程Binder通信流程分析

现在一起来分析Server端接收(来自APP端)Binder数据的整个过程,还是以ServiceManager这个Server为例进行分析,这是一个至下而上的分析过程。

在分析之前先思考ServiceManager是什么?它其实是一个独立的进程,由init解析init.rc文件并由它创建,要早于zygote进程,ServiceManager的main函数进程文件位于:framework/native/cmds/servicemanager/main.cpp
这个main函数运行意味着系统的SM进程开始运行了。下面是ServiceManager在init.rc中的描述。

下面是ServiceManager.rc文件

 

上面的rc文件描述说明servicemanager是一个系统的关键服务进程,不能重启的,因为 它一旦重启,将会restart如healthd,zygote, audioserver, surfaceflinger, inputflinger等一系列重要的其它进程。

下面先给出一个非常重要的结论,就是ServiceManager的父类继承关系,最顶层的父类是IServiceManager和BBinder,后面的源码分析的时候这个很有用,否则看不懂代码。

 

 

大家知道,每个android系统关键进程或app进程启动时会先创建binder,我们从SM的进程代码进行分析,如下:

main.cpp->main()
  -->char* driver="/dev/binder";
     //启动初始化binder驱动:普通app进程是通过ProcessState::self()->new ProcessState()来启动进程然后在构造函数中初始化binder,
     //与SM启动创建binder一样
       sp<ProcessState> ps = ProcessState::initWithDriver(driver);
         -->return new ProcessState();//在构造函数中open_driver(driver);
       //实例化ServiceManager
       sp<ServiceManager> manager = new ServiceManager(std::make_unique(Access));
       
       //设置服务端的BBinder对象
       //所以manager就是一个BBinder对象:因为class ServiceManager: public os:BnServiceManager{}
       //而BnServiceManager继承关系是: class BnServiceManager: public ::android::BnInterface<IServiceManager>{ }
       //BnInterface的继承关系(位于Interface.h): class BnInterface: public BBinder{ }
       //综上,manager就是一个BBinder对象。
       //注意BnServerManager.h这个头文件是需要根据IServerManager.aidl文件自己去编译生成的(
       //可以使用AIDL命令去编译)
       IPCThreadState::self()->setTheContextObject(manager); 
         -->IPCThreadState.cpp->self():
               -->return new IPCThreadState(); //创建线程对象
            IPCThreadState.cpp->setTheContextObject(sp<BBinder> obj):
               -->the_context_object = obj;
       //设置成为binder驱动的context Manager,成为上下文的管理者,ps代表SM进程
       ps->becomeContextManager(nullptr, nullptr);

       //重点在下面:
       //通过Looper epoll机制处理binder事务
       sp<Looper> looper = Looper::prepare(false);
       //设置callback
       BinderCallback::setupTo(looper);
         //向Binder驱动发送BC_ENTER_LOOPER事务请求,并获得binder设备的文件描述符
         //监听binder_fd文件描述符的数据变化
         -->IPCThreadState::self()->setupPolling(&binder_fd);
            looper->addFd(binder_fd, Looper::POLL_CALLBACK,
                          Looper::EVENT_INPUT, cb, nullptr);
            -->//当binder驱动发来消息后:调用下面的回调事件处理:
                int handleEvent(int fd int event){
                    //从binder驱动接收到消息并处理。
                    IPCThreadState::self()->handlePolledCommands();
                      -->do //当读 缓存中数据未消费完时,持续循环读
                         {
                             result = getAndExecuteCommand();
                               -->result = talkWithDriver();//从Binder驱动读入数据mIn
                               -->cmd = mIn.readInt32(); //从数据中读取BR响应码
                               -->executeCommand(cmd);
                                  -->case BR_TRANSACTION: //走这个分支
                                       //对SM来说,使用the_context_object这个BBinder对象
                                       //而transact应该在SM的父类中定义即BBinder
                                       -->the_context_object->transact(tr.code,buffer,&reply,tr.flags);
                                            -->BBinder.cpp->transact():
                                                //这里注意,下面调用的其实是子类的onTransact(即BnServiceManager.h中定义,但这只是一个头文件)
                                                //更进一步分析,其实是调用由IServiceManager.aidl生成的Bn端的cpp文件中(需要自己编译)
                                                --> onTransact();
                                                      -->IServiceManager.cpp->BnServiceManager::onTransact():
                                                            -->getService(); //其实是它的孩子即ServiceManager的接口
                                                                 -->ServiceManager.cpp->getService(name, sp<IBinder> * outBinder);
                                                                       //返回Binder
                                                                       *outBinder = tryGetService(name, true);
                                                                          -->std::map<string16, sp<IBinder>> mNameToService; //维持一张表
                                                                                --> auto it = mNameToService.find(name);
                                                                                    service = &(it->second); //取出Service;
                                                                                    out = service->binder;
                                                                                    return out;
                                                                          
                                                                       
                         }while(mIn.dataPosition() < mIn.dataSize());  
                         //当我们清空执行完所有的命令后,最后处理BR_DECREFS和BR_RELEASE
                         ProcessPendingDerefs();
                         FlushCommands();  
                            
                    
                }

上面分析的应该比较详细了,下面再总结下整体流程:

总结:

  1. binder驱动收到请求后, SM的looperCallBack回调会进行处理(BinderCallback- >handleEvent)
  2. 然后调用IPCThread::self()->handlePolledCommands()解读命令,向上分发
  3. the_context_object(注意这是一个BBinder对象)即BBinder->transact();
  4. 转交给BBinder的子类BnServiceManager.onTransact()处理,但这个是AIDL提供的代码,所以真正实现的是ServiceManager.getService();

最后再画一张图描述下整个过程:

 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【人脸考勤项目】

本项目主要是基于Opencv完成的人脸识别的考勤系统 人脸检测器的5种实现方法 方法一&#xff1a;haar方法进行实现&#xff08;以下是基于notebook进行编码&#xff09; # 步骤 # 1、读取包含人脸的图片 # 2.使用haar模型识别人脸 # 3.将识别结果用矩形框画出来# 导入相关包 …

ARM开发,stm32mp157a-A7核中断实验(实现按键中断功能)

1.实验目的&#xff1a;实现KEY1/LEY2/KE3三个按键&#xff0c;中断触发打印一句话&#xff0c;并且灯的状态取反&#xff1b; key1 ----> LED3灯状态取反&#xff1b; key2 ----> LED2灯状态取反&#xff1b; key3 ----> LED1灯状态取反&#xff1b; 2.分析框图: …

ACL2023 Prompt 相关文章速通 Part 1

Accepted Papers link: ACL2023 main conference accepted papers 文章目录 Accepted PapersPrompter: Zero-shot Adaptive Prefixes for Dialogue State Tracking Domain AdaptationQuery Refinement Prompts for Closed-Book Long-Form QAPrompting Language Models for Lin…

爬虫逆向实战(二十一)-- 某某点集登录与获取数据

登录 一、数据接口分析 主页地址&#xff1a;某某点集 1、抓包 通过抓包可以发现登录接口是phonePwdLogin 2、判断是否有加密参数 请求参数是否加密&#xff1f; 通过查看“载荷”模块可以发现有pwd和sig两个加密参数 请求头是否加密&#xff1f; 无响应是否加密&#x…

卡尔曼滤波

第一章知识点回顾 表1变量符号对照表 1.1数学期望 数学期望表示为每次可能的结果乘上结果概率的总和。 1.1.1 数学期望的性质 假设常数为 C &#xff0c;随机变量 X 和 Y &#xff0c;则 1.2 方差&#xff08;variance&#xff09; 概率论中和统计中的方差反映单个&…

Java进阶篇--进程和线程的区别

进程和线程 进程 在一个操作系统中&#xff0c;每个独立执行的程序都可称之为一个进程&#xff0c;也就是“正在运行的程序”。目前大部分计算机上安装的都是多任务操作系统&#xff0c;即能够同时执行多个应用程序&#xff0c;最常见的有Windows、Linux、Unix等。比如在Wind…

S波形及鱼眼扭曲源码

三角波形扭曲&#xff1a; void sinwave(cv::Mat& src,cv::Mat& dst) {dst.create(src.rows, src.cols, CV_8UC3);dst.setTo(0);src.copyTo(dst);int PI 3.1415;int RANGE dst.cols/2;for (int i 0; i < dst.rows; i) {double temp (dst.cols - RANGE) / 2 (d…

Git,分布式版本控制工具

1.为常用指令配置别名&#xff08;可选&#xff09; 打开用户目录&#xff0c;创建.bashrc文件 &#xff08;touch ~/.bashrc&#xff09; 2.往其输入内容 #用于输出git提交日志 alias git-loggit log --prettyoneline --all --graph --abbrev-commit #用于输出当前目录所有文…

意外发现Cortex-M内核带的64bit时间戳,比32bit的DWT时钟周期计数器更方便,再也不用担心溢出问题了

视频&#xff1a; https://www.bilibili.com/video/BV1Bw411D7F5 意外发现Cortex-M内核带的64bit时间戳&#xff0c;比32bit的DWT时钟周期计数器更方便&#xff0c;再也不用担心溢出问题了 介绍&#xff1a; 看参数手册的Debug章节&#xff0c;System ROM Table里面带Timestam…

首轮征稿 | 2024年第二届先进无人飞行系统国际会议(ICAUAS 2024)

会议简介 Brief Introduction 2024年第二届先进无人飞行系统国际会议(ICAUAS 2024) 会议时间&#xff1a;2024年4月5日-7日 召开地点&#xff1a;中国武汉 大会官网&#xff1a;ICAUAS 2024-2024 2nd International Conference on Advanced Unmanned Aerial Systems 由华中科技…

软件测试框架实战:Python+Slenium搭建Web自动化测试框架全教程

PythonSelenium是一种流行的Web自动化测试框架&#xff0c;可以模拟真实的用户操作&#xff0c;对网页进行功能和样式的验证。要通过selenium测试网页&#xff0c;需要以下几个步骤&#xff1a; 安装selenium库和浏览器驱动 。 使用selenium提供的方法来控制浏览器窗口大小、后…

图像检索,目标检测map的实现

一、图像检索指标Rank1,map 参考&#xff1a;https://blog.csdn.net/weixin_41427758/article/details/81188164?spm1001.2014.3001.5506 1.Rank1: rank-k&#xff1a;算法返回的排序列表中&#xff0c;前k位为存在检索目标则称为rank-k命中。 常用的为rank1&#xff1a;首…

老人摔倒智能识别检测算法

老人摔倒智能识别检测算法通过yolov8深度学习算法模型架构&#xff0c;老人摔倒智能识别检测算法能够实时监测老人的活动状态及时发现摔倒事件&#xff0c;系统会立即触发告警&#xff0c;向相关人员发送求助信号&#xff0c;减少延误救援的时间。YOLOv8 算法的核心特性和改动可…

对于pycharm 运行的时候不在cmd中运行,而是在python控制台运行的情况,如何处理?

对于pycharm 运行的时候不在cmd中运行&#xff0c;而是在python控制台运行的情况&#xff0c;如何处理&#xff1f; 比如&#xff0c;你在运行你的代码的时候 它总在python控制台运行&#xff0c;十分难受 解决方法 在pycharm中设置下即可&#xff0c;很简单 选择运行点击…

XSS攻击与防御

目录 一、环境配置 kali安装beef contos7安装dvwa 二、XSS攻击简介 三、XSS攻击的危害 四、xSS攻击的分类 五、XSS产生的原因 六、构造XSS攻击脚本 (一)基础知识 常用的html标签 常用的js脚本 (二)构造脚本的方式弹窗警告 七、自动XSS攻击 (一)BeEF简介 (二)BeEF…

亲测influxdb安装为window后台服务

InfluxDB 安装 64bit&#xff1a;https://dl.influxdata.com/influxdb/releases/influxdb-1.7.4_windows_amd64.zip 解压安装包 修改配置文件 [meta]# Where the metadata/raft database is storeddir "D:/influxdb/meta"...[data]# The directory where the TSM…

容器内执行命令

上篇文章向读者介绍了一个Nginx的例子&#xff0c;对于Nginx这样一个容器而言&#xff0c;当它启动成功后&#xff0c;我们不可避免的需要对Nginx进行的配置进行修改&#xff0c;那么这个修改要如何完成呢&#xff1f;且看下文。 依附容器 docker attach 依附容器这个主要是…

3D姿态相关的损失函数

loss_mpjpe: 计算预测3D关键点与真值之间的平均距离误差(MPJPE)。 loss_n_mpjpe: 计算去除尺度后预测3D关键点误差(N-MPJPE),评估结构误差。 loss_velocity: 计算3D关键点的速度/移动的误差,评估运动的平滑程度。 loss_limb_var: 计算肢体长度的方差,引导生成合理的肢体长度…

最新人工智能源码搭建部署教程/ChatGPT程序源码/AI系统/H5端+微信公众号版本源码

一、AI系统 如何搭建部署人工智能源码、AI创作系统、ChatGPT系统呢&#xff1f;小编这里写一个详细图文教程吧&#xff01; SparkAi使用Nestjs和Vue3框架技术&#xff0c;持续集成AI能力到AIGC系统&#xff01; 1.1 程序核心功能 程序已支持ChatGPT3.5/GPT-4提问、AI绘画、…

Python加入Excel--生产力大提高|微软的全方面办公

Python作为一种功能强大的编程语言&#xff0c;已经逐渐成为了数据分析、机器学习、Web开发等领域的主流语言之一。而将Python集成到Excel中&#xff0c;则可以为Excel用户提供更加强大的数据处理和分析能力&#xff0c;同时也可以为Python开发者提供更加便捷的数据处理和可视化…