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

news2024/10/5 14:28:56

现在一起来分析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();

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

 

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

windows11不允许安装winpcap4.1.3

问题&#xff1a;下载安装包后在安装时显示与电脑系统不兼容&#xff0c;不能安装。 原因&#xff1a;winpcap是一个用于Windows操作系统的网络抓包库&#xff0c;有一些安全漏洞&#xff0c;存在被黑客攻击的风险。Windows11为了加强系统安全而禁用了这个库&#xff0c;因此不…

java.8 - java -overrideoverload 重写和重载

重写(Override) 重写是子类对父类的允许访问的方法的实现过程进行重新编写, 返回值和形参都不能改变。即外壳不变&#xff0c;核心重写&#xff01; 重写的好处在于子类可以根据需要&#xff0c;定义特定于自己的行为。 也就是说子类能够根据需要实现父类的方法。 重写方法不…

【GAMES202】Real-Time Environment Mapping1—实时环境光照1

一、Distance field soft shadows Inigo Quilez :: computer graphics, mathematics, shaders, fractals, demoscene and more (iquilezles.org) 在开始我们的实时环境光照之前&#xff0c;我们再说一种现在的实现实时软阴影的方式&#xff0c;也就是Distance field soft shado…

SpringBoot实现文件上传和下载笔记分享(提供Gitee源码)

前言&#xff1a;这边汇总了一下目前SpringBoot项目当中常见文件上传和下载的功能&#xff0c;一共三种常见的下载方式和一种上传方式&#xff0c;特此做一个笔记分享。 目录 一、pom依赖 二、yml配置文件 三、文件下载 3.1、使用Spring框架提供的下载方式 3.2、通过IOUti…

分布式 - 服务器Nginx:一小时入门系列之 return 指令

文章目录 1. return 指令语法2. return code URL 示例3. return code text 示例4. return URL 示例 1. return 指令语法 return指令用于立即停止当前请求的处理&#xff0c;并返回指定的HTTP状态码和响应头信息&#xff0c;它可以用于在Nginx中生成自定义错误页面&#xff0c;…

分布式事务-seata框架

文章目录 分布式事务0.学习目标1.分布式事务问题1.1.本地事务1.2.分布式事务1.3.演示分布式事务问题 2.理论基础2.1.CAP定理2.1.1.一致性2.1.2.可用性2.1.3.分区容错2.1.4.矛盾 2.2.BASE理论2.3.解决分布式事务的思路 3.初识Seata3.1.Seata的架构3.2.部署TC服务3.3.微服务集成S…

CAPL - Panel和TestModule结合实现测试项可选

目录 一、定义脚本编号和脚本组编号 1、测试组定义 2、测试脚本编号定义

【C++】初步认识模板

&#x1f3d6;️作者&#xff1a;malloc不出对象 ⛺专栏&#xff1a;C的学习之路 &#x1f466;个人简介&#xff1a;一名双非本科院校大二在读的科班编程菜鸟&#xff0c;努力编程只为赶上各位大佬的步伐&#x1f648;&#x1f648; 目录 前言一、泛型编程二、函数模板2.1 函…

Java10(异常处理)

0.复习面向对象 1.异常的体系结构 异常&#xff1a;在Java语言中&#xff0c;将程序执行中发生的不正常情况.(开发中的语法错误和逻辑错误不是异常) 异常事件分两类&#xff08;它们上一级为java.lang.Throwable&#xff09;&#xff1a; Error Java虚拟机无法解决的严重问…

算法通过村第三关-数组黄金笔记|数组难解

文章目录 前言数组中出现超过一半的数字数组中只出现一次的数字颜色的分类问题(荷兰国旗问题)基于冒泡排序的双指针&#xff08;快慢指针&#xff09;基于快排的双指针&#xff08;对撞指针&#xff09; 总结 前言 提示&#xff1a;苦不来自外在环境中的人、事、物&#xff0c;…

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

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

Vue3.0极速入门- 目录和文件说明

目录结构 以下文件均为npm create helloworld自动生成的文件目录结构 目录截图 目录说明 目录/文件说明node_modulesnpm 加载的项目依赖模块src这里是我们要开发的目录&#xff0c;基本上要做的事情都在这个目录里assets放置一些图片&#xff0c;如logo等。componentsvue组件…

加快edge网页的下载速度

1、 edge://flags/#enable-parallel-downloading、 2、 点击enabled

Leetcode每日一题:1448. 统计二叉树中好节点的数目(2023.8.25 C++)

目录 1448. 统计二叉树中好节点的数目 题目描述&#xff1a; 实现代码与解析&#xff1a; dfs 原理思路&#xff1a; 1448. 统计二叉树中好节点的数目 题目描述&#xff1a; 给你一棵根为 root 的二叉树&#xff0c;请你返回二叉树中好节点的数目。 「好节点」X 定义为&…

谈谈子网划分的定义、作用、划分方式以及案例

个人主页&#xff1a;insist--个人主页​​​​​​ 本文专栏&#xff1a;网络基础——带你走进网络世界 本专栏会持续更新网络基础知识&#xff0c;希望大家多多支持&#xff0c;让我们一起探索这个神奇而广阔的网络世界。 目录 一、子网划分的定义 二、子网掩码的作用 1、…

[管理与领导-51]:IT基层管理者 - 8项核心技能 - 6 - 流程

前言&#xff1a; 管理者存在的价值就是制定目标&#xff0c;即目标管理、通过团队&#xff08;他人&#xff09;拿到结果。 要想通过他人拿到结果&#xff1a; &#xff08;1&#xff09;目标&#xff1a;制定符合SMART原则的符合业务需求的目标&#xff0c;团队跳一跳就可以…

【mysql是怎样运行的】-EXPLAIN详解

文章目录 1.基本语法2. EXPLAIN各列作用1. table2. id3. select_type4. partitions5. type 1.基本语法 EXPLAIN SELECT select_options #或者 DESCRIBE SELECT select_optionsEXPLAIN 语句输出的各个列的作用如下&#xff1a; 列名描述id在一个大的查询语句中每个SELECT关键…

Unity——后期处理举例

Post Processing&#xff08;后期处理&#xff09;并不属于特效&#xff0c;但现代的特效表现离不开后期处理的支持。本文以眩光&#xff08;Bloom&#xff09;为例&#xff0c;展示一种明亮的激光的制作方法 1、安装后期处理扩展包 较新的Unity版本已经内置了新版的后期处理扩…

2022年03月 C/C++(四级)真题解析#中国电子学会#全国青少年软件编程等级考试

第1题&#xff1a;拦截导弹 某国为了防御敌国的导弹袭击&#xff0c; 发展出一种导弹拦截系统。 但是这种导弹拦截系统有一个缺陷&#xff1a; 虽然它的第一发炮弹能够到达任意的高度&#xff0c;但是以后每一发炮弹都不能高于前一发的高度。 某天&#xff0c; 雷达捕捉到敌国的…

Linux内核学习(十)—— 块 I/O 层(基于Linux 2.6内核)

目录 一、剖析一个块设备 二、缓冲区和缓冲区头 三、bio 结构体 四、请求队列 五、I/O 调度程序 系统中能够随机&#xff08;不需要按顺序&#xff09;访问固定大小数据片&#xff08;chunks&#xff09;的硬件设备称作块设备&#xff0c;这些固定大小的数据片就称作块。最…