基于问题学习安卓系统架构

基于问题学习安卓系统架构

1 原理

本节要了解、弄懂安卓系统架构的原理,首先将安卓系统架构完全分析清楚,再根据下载好的Android8的源码,将源码目录中的内容与系统架构联合在一起,最后总结为什么安卓系统架构要这么设计。

1.1 什么是安卓系统架构

安卓系统架构,就是从底层硬件到高层软件的一整套技术体系,用户使用的移动端设备如果使用安卓系统搭建,那么用户就可以使用安卓平台上的应用,安卓系统架构图如下:

在这里插入图片描述

从顶层到底层依次是:APP --> Framework --> Native --> HAL --> Kernal,接下来对这些层进行三个层次的分析:为什么要有它、是什么、在哪里,一切要从为什么入手。

APP层
  1. why

    我今天早上睡过头迟到了,那么我就在想,如果有一个闹钟就好了,于是就出现了手机闹钟APP,就解决了用户每天起床需要有人按时提醒上班的需求。所以当应用设计出来后,一些页面、页面跳转、功能都需要在APP层进行实现。

  2. what

    就如同英文直译过来一样,是一些应用软件,比如系统自带的应用如:时钟、计算器,和用户自己安装的应用如:微信、微博。应用需要给用户提供好看的外观和满足需求的功能,是安卓系统架构中用户看得见摸得着的第一个东西,直接和用户的体验挂钩。

  3. where

    以apk的形式安装在用户的手机上,打开手机一看全是。

    源码根目录中的packages目录对应着系统应用层,如下所示。

    packages目录描述
    apps核心应用程序
    experimental第三方应用程序
    inputmethods输入法目录
    providers内容提供者目录
    screensavers屏幕保护
    services通信服务
    wallpapers墙纸
Framework层
  1. why

    当产品的定位和设计出来后,安卓软件工程师就要进行开发,手机上的产品,都是软件和硬件一起协助开发完成的,那是不是每次开发产品的时候都要将硬件和软件都写好呢?当然不是,这样开发的效率太低、所需要的开发知识的门槛太高了,所以就需要有人帮助安卓应用工程师把一些与系统打交道、通用的东西都封装好,变成有描述、可以调用的API接口,达到提效率、降门槛的效果。

  2. what

    Framework层是一些封装好的api,主要由Java代码实现。当安卓应用工程师在编程的时候,就可以调用Framework层的api对系统层面比如电源管理、消息队列、包管理等做操作。Framework同下层打交到的方式有很多种,参考Android Framework层和Native层通信的6种方式,同上层打交到的方式就是抽象出各种Java接口。

    往上层看,在AS中开发app的时候,import的各种android.*,就是Framework层的api。

    package com.leo.helloworld;
    
    import android.app.ActivityManager;// 这边都是
    import android.content.Context;
    import android.os.Bundle;
    
    import androidx.appcompat.app.AppCompatActivity;
    
    public class leo extends AppCompatActivity {
    
        public  void activityManagerDemo(Context context){
            ActivityManager activityManager =
                    (ActivityManager)(context.getSystemService(android.content.Context.ACTIVITY_SERVICE )) ;
            return;
        }
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_leo1);
        }
    }
    

    往下层看,Framework层提供了jni.h的文件去连接Native中的C或C++代码,达到了Java代码调用C或C++代码的效果。

    下面引用网上对于 ‘Framework是什么’ 的回答:

    直接翻译的意思是架构,但这样说可能不懂,下面我从两个方面来给你说吧:

    一是比喻来说,假设你现在要盖楼房,framework就好比一个建筑公司,它里面有专门采集石料的,专门的租夹板的,专门的磨砂,搬砖的,运输的等等一系列的,你需要做的就是要通过这家建筑公司来盖楼,比如说你要采集石料,你通过公司采购部门,直接采集来了石料,然后通过他们进行一系列的工作,这要比你自己去河里采砂,到山上去炸石头(这些活都是不使用framework的底层嵌入式开发人员做的)要简单的多,这也是为什么farmework要高效的多,所以说,对于开发人员来说,他就像是会为开发省很多事情,但这种框架下开发的软件有一定的依赖性,所以,对于不是开发人员的用户来说,如果你的电脑上有这种框架下开发的软件,你必须有这个框架软件才可以,就好像你如果要用扩展名为EXE的应用程序,你必须先有windows系统一样

    另外呢,就是通过实际案例来说明framework

    如果我们要完成屏幕打印“hello world”,你如果没用框架软件,你或许会先了解底层如何实现在屏幕上显示字符,又如何启动显示器,如何控制字符位置等等,然后再考虑如何打印hello world

    但是在framework下,框架下的Console类下有个静态方法Write直接实现了打印,你只需要调用这个方法,然后告诉他你要打印的信息就可以了,Console.Write(“hello world”)

    不管你是不是开发人员,解释的觉得还是透彻的,不懂的话可以再追问,希望能得到最佳~

    引用来源:XJZWX

    Framework层主要提供的组件如下:

    名称功能描述
    Activity Manager(活动管理器)管理各个应用程序生命周期以及通常的导航回退功能
    Location Manager(位置管理器)提供地理位置以及定位功能服务
    Package Manager(包管理器)管理所有安装在Android系统中的应用程序
    Notification Manager(通知管理器)使得应用程序可以在状态栏中显示自定义的提示信息
    Resource Manager(资源管理器)提供应用程序使用的各种非代码资源,如本地化字符串、图片、布局文件、颜色文件等
    Telephony Manager(电话管理器)管理所有的移动设备功能
    Window Manager(窗口管理器)管理所有开启的窗口程序
    Content Providers(内容提供器)使得不同应用程序之间可以共享数据
    View System(视图系统)构建应用程序的基本组件
  3. where

    应用框架层的主要实现代码在/frameworks/base和/frameworks/av目录下,其中/frameworks/base目录结构如下所示:

    /frameworks/base目录描述/frameworks/base目录描述
    api定义APIcmds重要命令:am、app_proce等
    core核心库data字体和声音等数据文件
    docs文档graphics图形图像相关
    include头文件keystore和数据签名证书相关
    libslocation地理位置相关库
    media多媒体相关库native本地库
    nfc-extrasNFC相关obex蓝牙传输
    opengl2D/3D 图形APIpackages设置、TTS、VPN程序
    saxXML解析器services系统服务
    telephony电话通讯管理test-runner测试工具相关
    tests测试相关tools工具
    wifiwifi无线网络

    参考链接:Android系统架构与系统源码目录

Native/Art
Native: C/C++
  1. why

    首先,安卓的应用和framework层主要使用Java语言开发,但是Java是高级语言的一种,虽然在编程时比较容易学习,但是如果要完成一些复杂运算和偏向底层的操作,Java非常难实现,而使用C/C++会很简单,所以一般会使用虚拟机:JVM等,将Java代码编译后再解释成机器语言,来驱动硬件。那么除开使用虚拟机将.class文件解释后变成机器可识别的文件,我们可以通过给Java代码加上native关键字、Java代码利用jni.h文件调用C/C++代码的方式,把复杂的Java难以实现的功能,交给C/C++代码来实现。

  2. what

    常见一些本地服务和一些链接库等。这一层的一个特点就是通过C和C++语言实现。

  3. where

    C/C++程序库并不完全在一个目录中,主要的C/C++程序库如:

    名称功能描述
    OpenGL ES3D绘图函数库
    Libc从BSD继承来的标准C系统函数库,专门为基于嵌入式Linux的设备定制
    Media Framework多媒体库,支持多种常用的音频、视频格式录制和回放。
    SQLite轻型的关系型数据库引擎
    SGL底层的2D图形渲染引擎
    SSL安全套接层,是为网络通信提供安全及数据完整性的一种安全协议
    FreeType可移植的字体引擎,它提供统一的接口来访问多种字体格式文件

    要查看framework层对应的native层源码,参考:如何查找native方法所对应的底层文件

Art
  1. why

    在安卓系统中,APP开发和Framework层开发都是Java代码,Java代码执行在虚拟机上,如:JVM。Art也是虚拟机的一种,所以其存在的理由就是为了支持Java代码编译、解释。

  2. what

    Art,Android Runtime,是安卓手机上运行的虚拟机,Android4.4及以前使用的都是Dalvik虚拟机,Android5.0才开始使用Art。

    为什么不使用JVM做为虚拟机?

    Java VM是以基于栈的虚拟机(Stack-based),而Dalvik是基于寄存器的虚拟机(Register-based)。 显然,后者最大的好处在于可以根据硬件实现更大的优化,这更适合移动设备的特点。DVM非常适合在移动终端上使用,与PC相比,它不需要很快的CPU和大量的内存空间。

    为什么要从Dalvik变为Art?

    • Dalvik
      Android4.4及以前使用的都是Dalvik虚拟机,我们知道Apk在打包的过程中会先将Java等源码通过javac编译成.class文件,但是我们的Dalvik虚拟机只会执行.dex文件,这个时候dx会将.class文件转换成Dalvik虚拟机执行的.dex文件。Dalvik虚拟机在启动的时候会先将.dex文件转换成快速运行的机器码,又因为65535这个问题,导致我们在应用冷启动的时候有一个合包的过程,最后导致的一个结果就是我们的app启动慢,这就是Dalvik虚拟机的JIT特性(Just In Time)。
    • Art
      ART虚拟机是在Android5.0才开始使用的Android虚拟机,ART虚拟机必须要兼容Dalvik虚拟机的特性,但是ART有一个很好的特性AOT(ahead of time),这个特性就是我们在安装APK的时候就将dex直接处理成可直接供ART虚拟机使用的机器码,ART虚拟机将.dex文件转换成可直接运行的.oat文件,ART虚拟机天生支持多dex,所以也不会有一个合包的过程,所以ART虚拟机会很大的提升APP冷启动速度。

    简而言之,就是Dalvik是边运行边解释.dex文件,Art是启动时就预解释.dex文件为.oat文件,Dalvik启动时更快,Art运行时更快。

    参考链接

    Android Dalvik虚拟机和ART虚拟机对比

    一篇文章带你了解 Android的 JIT 、AOT、Dalvik、ART ,不再傻傻分不清

    JVM:.java文件->.class文件->.jar文件

    DVM:.java文件->.class文件->.dex文件->.apk文件

    ART:.java文件->.class文件->.dex文件->.oat文件->.apk文件

  3. where

    • .oat文件;
    • art目录。
HAL层
  1. why

    设想一下使用Java开发后端的情况,似乎在JVM后,就直接是操作系统,利用操作系统内提供的对机器的指令完成软件对硬件的操作,但是为啥安卓系统架构中Art之下还需要有一个硬件抽象层?下面引用一下罗老师对于HAL层的介绍:

    Android的硬件抽象层,简单来说,就是对Linux内核驱动程序的封装,向上提供接口,屏蔽低层的实现细节。也就是说,把对硬件的支持分成了两层,一层放在用户空间(User Space),一层放在内核空间(Kernel Space),其中,硬件抽象层运行在用户空间,而Linux内核驱动程序运行在内核空间。为什么要这样安排呢?把硬件抽象层和内核驱动整合在一起放在内核空间不可行吗?从技术实现的角度来看,是可以的,然而从商业的角度来看,把对硬件的支持逻辑都放在内核空间,可能会损害厂家的利益。我们知道,Linux内核源代码版权遵循GNU License,而Android源代码版权遵循Apache License,前者在发布产品时,必须公布源代码,而后者无须发布源代码。如果把对硬件支持的所有代码都放在Linux驱动层,那就意味着发布时要公开驱动程序的源代码,而公开源代码就意味着把硬件的相关参数和实现都公开了,在手机市场竞争激烈的今天,这对厂家来说,损害是非常大的。因此,Android才会想到把对硬件的支持分成硬件抽象层和内核驱动层,内核驱动层只提供简单的访问硬件逻辑,例如读写硬件寄存器的通道,至于从硬件中读到了什么值或者写了什么值到硬件中的逻辑,都放在硬件抽象层中去了,这样就可以把商业秘密隐藏起来了。也正是由于这个分层的原因,Android被踢出了Linux内核主线代码树中。大家想想,Android放在内核空间的驱动程序对硬件的支持是不完整的,把Linux内核移植到别的机器上去时,由于缺乏硬件抽象层的支持,硬件就完全不能用了,这也是为什么说Android是开放系统而不是开源系统的原因。

    参考链接Android硬件抽象层(HAL)概要介绍和学习计划

    我的理解是,其实安卓系统架构中的HAL层和Kernal层组合起来,起到的是操作系统的作用,但是为了将关键源码不开源,所以将一些不能公布的源码放在HAL层,一些能开源的代码放在Kernal层。

  2. what

    硬件抽象层是位于操作系统内核与硬件电路之间的接口层,其目的在于将硬件抽象化,为了保护硬件厂商的知识产权,它隐藏了特定平台的硬件接口细节,为操作系统提供虚拟硬件平台,使其具有硬件无关性,可在多种平台上进行移植。

    在HAL层,代码也是保存在jni.h和.c类型的文件中,与Framework层调用Native层不一样的是,HAL层的代码需要遵循固定的格式、命名进行编写。

    参考链接:Android中HAL如何向上层提供接口总结-hw_device_t

  3. where

    • hardware/libhardware/
    • hardware/libhardware_legacy/
    • hardware/xxxx/
Kernal层
  1. why

    如果说上面的所有层,都是决定逻辑上去驱动那个硬件,那么需要有一层只负责对硬件做操作,不是说上面的所有层没办法对硬件做操作,毕竟大家都是图灵完备的Java/C/C++代码,而是要把相同类似的事物放在一起,这样可以解耦,所以Kernal层,主要负责对硬件做操作,也叫驱动层。

    为什么安卓要采用linux作为操作系统呢?

    Android系统是基于Linux内核的,这一层为Android设备的各种硬件提供了底层的驱动(如显示,音频,照相机,蓝牙,WI-FI,电源管理等等),那么Android为什么会选择采用linux呢?原因与Linux的特性有关,内核作为一个抽象层存在硬件和软件之间,强大的内存管理和进程管理,基于权限的安全模式,支持共享库,经过认证的驱动模式,Linux本身就是开源项目等等。

  2. what

    Android 的核心系统服务基于Linux 内核,在此基础上添加了部分Android专用的驱动。系统的安全性、内存管理、进程管理、网络协议栈和驱动模型等都依赖于该内核。

    主要驱动:增强显示驱动、键盘驱动、Flash内存驱动、照相机驱动、音频驱动、蓝牙驱动、WiFi驱动、Binder IPC驱动、Power Management(电源管理),包括硬件时钟,内存分配和共享,低内存管理,kernel调试,日志设备,android IPC机制,电源管理等。

    如果要写一个驱动应该怎样写呢?Android 从上层到底层-----kernel层

  3. where

    主要在Driver目录下。

    1、Binder IPC驱动:基于OpenBinder框架的一个驱动,用于提供 Android平台的进程间通信功能。源代码位于drivers/staging/android/binder.c。

    2、电源管理(PM) :一个基于标准Linux电源管理系统的轻量级Android电源管理驱动,针对嵌入式设备做了很多优化,比如电池电量。源代码位于:kernel/power/earlysuspend.c、kernel/power/consoleearlysuspend.c、kernel/power/fbearlysuspend.c、kernel/power/wakelock.c、kernel/power/userwakelock.c

    3、低内存管理器:比Linux的标准的OOM机制更加灵活,它可以根据需要杀死进程以释放需要的内存。源代码位于 drivers/staging/ android/lowmemorykiller.c。

    4、匿名共享内存: 为进程间提供大块共享内存,同时为内核提供回收和管理这个内存的机制。源代码位于mm/ashmem.c。

    5、 PMEM :用于向用户空间提供连续的物理内存区域,DSP和某些设备只能工作在连续的物理内存上。源代码位于drivers/misc/pmem.c。

    6、 Logger :一个轻量级的日志设备,用于抓取Android系统的各种日志。源代码位于drivers/staging/android/logger.c。

    7、 Alarm :提供了一个定时器,用于把设备从睡眠状态唤醒,同时它还提供了一个即使在设备睡眠时也会 运行的时钟基准。源代码位于drivers/rtc/alarm.c。

    8、USB Gadget:驱动 一个基于标准 Linux USB gadget驱动框架的设备驱动,Android的USB驱动是基于gaeget框 架的。源代码位于drivers/usb/gadget/。

    9、Ram Console: 为了提供调试功能,Android允许将调试日志信息写入一个被称为RAM Console的设备里,它是一个基于RAM的Buffer。源代码位于drivers/staging/android / ram_console.c。

    10、timed device: 提供了对设备进行定时控制的功能,目前支持vibrator和LED设备。源代码位于drivers/staging/android /timed_output.c(timed_gpio.c)。

    11、Yaffs2 :是文件系统 Android采用Yaffs2作为MTD nand flash文件系统,源代码位于fs/yaffs2/目录下。Yaffs2是一个快速稳定的应用于NAND和NOR Flash的跨平台的嵌入式设备文件系统,同其他Flash文件系统相比,Yaffs2能使用更小的内存来保存其运行状态,因此它占用内存小。Yaffs2的垃圾回收非常简单而且快速,因此能表现出更好的性能。Yaffs2在大容量的NAND Flash上的性能表现尤为突出,非常适合大容量的Flash存储。

1.2 Android8源码与系统架构的关系

从安卓8的源码目录入手,分析安卓系统架构的每一层,大概在源码中的什么位置。

源码目录结构

目录图如下:

在这里插入图片描述

源码目录描述
Android源码根目录描述
art全新的ART运行环境
bionic系统C库
bootable启动引导相关代码
build存放系统编译规则及generic等基础开发包配置
ctsAndroid兼容性测试套件标准
dalvikdalvik虚拟机
developers开发者目录
development应用程序开发相关
device设备相关配置
docs参考文档目录
external开源模组相关文件
frameworks应用程序框架,Android系统核心部分,由Java和C++编写
hardware主要是硬件抽象层的代码
kernelLinux Kernal,需要单独去下载
libcore核心库相关文件
libnativehelper动态库,实现JNI库的基础
packages应用程序包
pdkPlug Development Kit 的缩写,本地开发套件
platform_testing平台测试
prebuiltsx86和arm架构下预编译的一些资源
sdksdk和模拟器
system底层文件系统库、应用和组件
toolchain工具链文件
tools工具文件
Makefile全局Makefile文件,用来定义编译规则

App层:packages

Framework层:frameworks

Native/ART层

​ NativeC/C++:bionic

​ Art:art

HAL层:hardware

Kernal层:kernel

1.3 为什么安卓系统架构要这么设计

思路:从整体架构分析,再从大到小,到每层分工来分析。

从0开始,什么都没有,我们收到需求:做一款能在手机上运行的应用,分析本质,就是软件和硬件的交互,完成一种满足用户需求的产品。那么现在开始开发了,写了很多代码,配合上硬件,能完成功能,那么这些代码里面,肯定必须得有软件能直接驱动硬件的代码,而这些代码肯定是最后被调用,又因为要和硬件打交道,C语言很合适,于是选择C语言编写,这时候把这些驱动硬件的代码拉出来放在一个文件夹里面,把这个文件夹叫做操作系统代码。由于在软件选语言的时候,觉得Java的可移植性好,所以选择用Java进行开发,接下来再看看写的代码,除去驱动硬件的代码后,发现有一些代码是用来写APP的页面、页面跳转之类的,那也把这些代码整合一下,放在一个文件夹里面,就叫业务代码吧。而Java开发,那必须得有虚拟机才能变成机器识别的代码,所以又将虚拟机的代码放在一个文件夹里,就叫虚拟机代码吧。

开发的某一天,我们忽然碰到一个很复杂的功能,Java实现起来太难了,这时候想到一个办法–使用C/C++来实现,然后用Java调用这些C/C++代码来实现功能,那也把这些C/C++代码也放在一个文件夹里,就叫调用的C/C++代码吧。

开发工作结束了,现在的项目结构是:业务代码、虚拟机代码、调用的C/C++代码、操作系统代码最后连接到硬件。

在休息两天后,又接到新的需求,要开发另外一款新的产品,这下根据上一款项目的代码,忽然发现,好像业务代码中,有一部分是可以重复使用的,比如一些位置、电话之类的通用模块,那新建一个文件夹,把这部分重复的代码也放在一个文件夹里面,就叫通用代码吧。这时候忽然收到通知,操作系统的代码要求要开源了,但是里面有一部分代码涉及商业机密不允许开源啊,于是把这部分无法开源的代码放在一个文件夹里,就叫不开源代码吧。

第二款APP开发结束了,现在的项目结构是:业务代码、通用代码、虚拟机代码、调用的C/C++代码、不开源代码、操作系统代码,对应了安卓系统架构的:APP层、Framework层、Art、Native、HAL层、Kernal层

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值