当前位置: 首页 > news >正文

execve系统调用_Framework 深入探索之 系统相关服务

5564e3287838cf9f52b2b0fa70e84ad9.png

这次我们来聊一聊系统相关服务,比如Zygote启动原理,SystemServer启动原理,如何进行添加一个系统服务等。 熟悉这些Android 底层知识更好的方便我们进行代码运行时,出现异常进行分析,每次堆栈信息都是从init进程开始,然后zygote进程,之前一直面对这些信息,都摸不着头脑,如果知晓这些相关信息,更好的让我们对整个应用的启动有了更深入理解,不再简单的停留在应用层上面。

推荐看看Android 进阶解密,从源码层讲解framework,对个人理解非常有帮助

先来说一下Zygote进行相关原理

Zygote 进程

那Zygote进程有什么作用 1. 首先启动SystemServer (因为需要Zygote 中的一些资源比如:常用类,JNI函数,主题资源,共享库) 2. 孵化应用进程

它有个启动三段式:进程启动->准备工作->Loop

Zygote 启动流程

进程怎么启动

  • Init 进程->加载配置文件init.rc,配置文件定义那些服务需要启动->通过forkexecve 系统调用来启动Zygote进程
    • 启动进程 (根据pid=0来判断是子进程还是父进程,为0是子进程)
      • fork+handler
      • fork+execve
  • 信号处理(sigchid)
    • 父进程通过fork来创建一个子进程,当子进程死亡父进程会收到这个信号来做一些操作,比如Zygote进程死亡,init进程就会收到这个信号,来重新启动Zygote进程

进程启动之后做了什么

  1. ZygoteNative世界
  • 启动Android虚拟机
  • 注册Android的关键JNI函数
  • 进入Java世界
  1. Zygote的Java世界
  • 预加载资源,孵化子进程用到的
  • fork创建SystemServer进程
  • 通过socket通信进入Loop循坏,当有新的请求,去处理,参数列表通过AMS进行跨进程发送,在子进程进行执行ActivityThread.main()函数

Zygote 注意细节

  • Zygote fork 要单线程,避免线程死锁,状态不一致
  • Zygote 的IPC没有采用binder(binder在应用程序进程启动之后创建的binder机制),采用的是本地Socket通信

Zygote的IPC通信机制为什么不采用binder

  1. zygoteservice manager先启动;从这个意义上,他没有 service manager可以注册,所以没法用 binder
  2. 因为他们两个都是 init 进程启动的,就算先启动 service manager,也不能保存 zygote 起来的时候 service manger 就已经初始化好了(这就需要额外的同步,太麻烦)
  3. 这个 socket的所有者是 rootgroup是system,只有系统权限的用户才能读写,这又多了一个安全保障(注意,这个 socket 是 Unix 域 Socket,不是 internet 域 Socket)

Android 系统启动流程

说完Zygote 进程启动,我们在说一下Android 系统启动流程,这里面就包括了SystemServer的启动流程,就不单独的讲一下

Zygote 进程启动

  • init进程通过fork方式创建Zygote进程
  • 启动虚拟机,注册jni函数
  • 预加载系统资源
  • 创建SystemServer进程并启动
  • 进入SocketLoop循环

SystemServer 进程启动(主要用于创建系统服务,比如AMS、PMS与WM都是它创建)

SystemServermain方法只调用了SystemServer的run方法 - 创建消息Looper - 加载动态库 liandroid_servers.so - 创建系统context - 启动引导服务,比如AMS、PowerManagerService与PackageManagerService等服务 - 启动核心服务,比如DropBoxManagerService、BatteryService等 - 启动其他服务,比如CamerManagerService、AlarmManagerService、WindowManagerService

  1. 启动Binder线程池,可以与其他进程通信
  2. 创建SystemServiceManager,用于对系统读物服务进程创建,启动与生命周期进程管理
  3. 启动各种系统服务

系统服务怎么启动

  • 系统服务怎么发布,让应用程序可见
    • publishBinderService方法中最终将Binder函数注册到了ServiceManager
  • 系统服务跑在什么线程
    • 工作线程(AMS,PMS,DisplayThread显示,FgThread前台任务,ioThread耗时任务,UIThread负责Ui线程->这里是子线程)
    • Binder 线程,应用跨进程调用在binder线程中

ServiceManager 启动与工作原理

SystemServer进程启动创建了ServiceManager,那我们就有必要再来讨论一下ServiceManager相关知识

ServiceManager 启动流程

  • 启动进程
  • 启用binder机制
  • 发布自己的服务
  • 等待并响应请求

怎么向ServiceManager添加服务

  • 获取binder对象
  • ServiceManager发起一个binder调用,需要两个参数服务名称及服务实体对象

怎么从ServiceManager获取服务

  • 获取ServiceManagerbinder对象
  • ServiceManager发起一个binder调用,带service名称就可以

系统服务

如何使用系统服务

通过getSystemService传入一个服务名称进可以获取,内部通过hashMapkey值进行获取,判断缓存中是否有service,没有就创建,缓存作用是在系统启动的时候预支一些服务放进去,后面再启动的时候并没有放入缓存中

系统服务注册原理

  • 通过addService方法进行注册,在SystemService启动时候进行注册系统服务
    • 启动binder机制
    • 启动各类系统服务
    • 进入Loop循环
  • 独立进程系统服务
    • 无论是在SystemService中服务,还是单独的进程系统服务,都需要在ServiceManager中进行注册,才能够使用服务

启用binder机制

  • 打开binder驱动
  • 映射内存,分配缓冲区
  • 启动binder线程,进入binder loop中循环

怎么添加一个系统服务

  • 为什么要添加系统服务
    • 用来让别人使用
  • 怎么样让别人用
    • 启动binder机制就可以IPC进程通信
    • 注册开发,让别人找到
  • 具体哪些事要干
    • 添加系统服务时机
      • 跑在单独进程,
        • 在init进程中修改配置,需要main入口函数
    • 服务端要做的事,做服务端初始化操作
    • 应用端做哪些事
      • 调用方式保存一直,注册一个服务

系统服务与binder服务区别

最后我们再聊一下系统服务与binder服务区别

在启动方式上有什么区别

  • 系统服务在systemService中启动,跑在binder线程中,做一些初始化操作,当client客户端有请求操作,在binder线程池中分发请求给对应的binder实体对象来进行处理,处理完再发送回复给客户端
  • 应用服务启动,由客户端发起,通过AMS启动

在注册方式上有什么区别

系统服务注册,都需要给binder实体对象注册到ServiceManager中,只有系统服务才可以注册 应用服务,应用端发起调用,给AMS,判断是否注册,注册,回调binder返回给应用,没有再进行binder注册,再回调给应用

在使用方式上有什么区别

  • 系统服务使用,通过getSystemService进行获取,内部缓存,hashmap
  • 应用服务使用,通过bindService进行绑定,然后进行调用

相关文章:

  • oracle雾化试图_Oracle 物化视图
  • 路由器桥接以后怎么找到_倒立不敢离墙怎么办?找到平衡只需4个方法,以后倒立不用靠墙...
  • 如何用excel计算断色断码_年薪二十万的造价就是用这套工程量自动计算Excel表格来计算工程量...
  • blob字段乱码怎么处理_这500多个字段引起的问题,大部分DBA都搞不定
  • 参数调整 新部署rac_zCloud如何进行自动化部署?
  • 一部分 数据 迁移_关于系统迁移,有哪些风险?又有哪些促进成功的因素?
  • 布尔类型_6. Go语言数据类型:字典与布尔类型
  • chord协议模拟实现_Modbus 通讯协议,每个工控人都应该了解的事
  • 方法的重载与重写_如何从jvm角度看懂类初始化、方法重载、重写
  • 简单代码画皮卡丘_超酷!用 Python 教你绘制皮卡丘和哆啦A梦
  • 分析函数hive计算均值_Hive第六天——Hive函数(开窗函数之累计统计)
  • 蓝卡攻略_剑与远征:4.18版本的新手攻略,崛起的三巨头
  • 关抢占 自旋锁_Linux学习第28节,什么是自旋锁?内核是如何设计,如何实现它的...
  • 2019pro与air怎么选_iPad Air 2019 VS iPad Pro 10.5 | 普通人的角度简单思考
  • mysql安装教程与启动_MySql安装启动两种方法教程详解
  • 【跃迁之路】【733天】程序员高效学习方法论探索系列(实验阶段490-2019.2.23)...
  • Angular 响应式表单之下拉框
  • centos安装java运行环境jdk+tomcat
  • codis proxy处理流程
  • CoolViewPager:即刻刷新,自定义边缘效果颜色,双向自动循环,内置垂直切换效果,想要的都在这里...
  • css的样式优先级
  • el-input获取焦点 input输入框为空时高亮 el-input值非法时
  • ERLANG 网工修炼笔记 ---- UDP
  • github指令
  • Java超时控制的实现
  • oschina
  • Python中eval与exec的使用及区别
  • Spring Cloud(3) - 服务治理: Spring Cloud Eureka
  • Transformer-XL: Unleashing the Potential of Attention Models
  • V4L2视频输入框架概述
  • weex踩坑之旅第一弹 ~ 搭建具有入口文件的weex脚手架
  • 搭建gitbook 和 访问权限认证
  • 大数据与云计算学习:数据分析(二)
  • 关于 Cirru Editor 存储格式
  • 基于遗传算法的优化问题求解
  • 让你成为前端,后端或全栈开发程序员的进阶指南,一门学到老的技术
  • 山寨一个 Promise
  • 原生Ajax
  • Unity3D - 异步加载游戏场景与异步加载游戏资源进度条 ...
  • 你学不懂C语言,是因为不懂编写C程序的7个步骤 ...
  • ​批处理文件中的errorlevel用法
  • (1/2)敏捷实践指南 Agile Practice Guide ([美] Project Management institute 著)
  • (C语言)fgets与fputs函数详解
  • (附源码)计算机毕业设计SSM教师教学质量评价系统
  • (每日持续更新)信息系统项目管理(第四版)(高级项目管理)考试重点整理 第13章 项目资源管理(七)
  • (转)【Hibernate总结系列】使用举例
  • (转)3D模板阴影原理
  • .class文件转换.java_从一个class文件深入理解Java字节码结构
  • .net MVC中使用angularJs刷新页面数据列表
  • .NET 程序如何获取图片的宽高(框架自带多种方法的不同性能)
  • .net 简单实现MD5
  • .NET 使用 ILRepack 合并多个程序集(替代 ILMerge),避免引入额外的依赖
  • .NET 事件模型教程(二)
  • .NET6实现破解Modbus poll点表配置文件
  • .NET版Word处理控件Aspose.words功能演示:在ASP.NET MVC中创建MS Word编辑器