Android系统的HAL层分析 (1)-- HAL的架构分析

news2024/9/30 5:31:49

目录

  • 说明
  • 1. Android系统内为何会要有HAL ?
  • 2. HAL_legacy和HAL对比
  • 3. HAL module的架构分析
    • 3.1 hw_module_t
    • 3.2 hw_module_methods_t
    • 3.3 hw_device_t
  • 4. 分析hardware.c
  • 5. 分析HAL的加载过程
  • 6. 分析硬件访问服务
  • 7. 官方实例mokoid分析

说明

  1. 在Android系统中有一个很特殊的HAL层,它的作用是什么呢?
  2. HAL是Android底层开发绕不开的Android独有机制,是操作系统上层和硬件驱动沟通的桥梁,通过这一系列的文章,你将对HAL有深入的理解。

1. Android系统内为何会要有HAL ?

  想必在了解Android系统之前,都会听说Android系统是一个开放的操作系统,那么不禁要问,这“开放”和Linux的“开源”的区别是啥?
  HAL层又叫硬件抽象层。它在Android体系中有着重要的意义,因为Android究竟是完全开源的还是完全不开源的秘密就在这一层。Google 将硬件厂商的驱动程序放在这一层。正是因为这层的代码没有开源,所以Android才被Linux家族删除。
  在Android系统中,HAL层是为保护一些硬件提供商的知识产权而提出的,位于Linux内核层之上。HAL实现了硬件抽象化,将硬件平台的差异隐藏,为上层提供统一的硬件平台,从而加快开发人员在不同的硬件平台上进行代码移植。
  就驱动开发的角度而言,HAL将Android框架与Linux内核隔离。主要原因有两方面:由于Linux内核要遵循GPL,根据此许可证,如果对Linux内核源码进行改动就必须公开其源码。如果Android系统的硬件驱动都在Linux的驱动模块中实现,就要将驱动源码完全公开。但是硬件设备商并不愿意将具体的细节公开,此类做法有损其利益。因此,Android系统源码采用Apache License2许可,它允许各厂家对Android系统源码进行改动但不公开。另一方面是因为Android对某些硬件有特殊的要求并没有标准的 Linux接口。
  Android的HAL层考虑Linux系统的设计要求。由于Linux对硬件的支持实现不能完全在用户空间,只有内核空间才具有特权对硬件设备进行操作。基于上述因素,Android驱动将对硬件的支持放在内核空间与用户空间,内核空间使用Linux驱动模块,但只提供硬件访问通道,而用户空间则以HAL模块的方式,在HAL层对硬件细节与参数进行封装,既实现Linux系统对代码公开的要求,也保护移动设备厂家各自的利益。

在Android系统中可以分为如下 6 种HAL:

  • 上层软件。
  • 内部以太网。
  • 内部通信CLIENT。
  • 用户接入口。
  • 虚拟驱动,设置管理模块
  • 内部通信SERVER。

在Android系统中,定义硬件抽象层接口的代码具有以下5个特点:

  • 硬件抽象层具有与硬件密切的相关性。
  • 硬件抽象层具有与操作系统无关性。
  • 接口定义的功能应包含硬件或系统所需硬件支持的所有功能。
  • 接口定义简单明了,太多接口函数会增加软件模拟的复杂性。
  • 具有可测性的接口设计有利于系统的软硬件测试和集成。

在Android 源码中,HAL 主要被保存在源码hardware目录中:
在这里插入图片描述

  • libhardware_legacy:过去的目录,采取了链接库模块观念来架构。
  • libhardware:新版的目录,被调整为用HAL stub观念来架构。
  • ril:是Radio接口层。
  • 其余目录为一些厂商定制的硬件HAL。

2. HAL_legacy和HAL对比

从Android源码上分析,HAL层主要对应的源码目录如下:

  • libhardware_legacy:过去的目录,采取了链接库模块观念来架构。
  • libhardware:新版的目录,被调整为用HAL stub观念来架构。

  libhardware_legacy 架构中HAL层采用的是共享库的方式,也就是直接函数调用的方式使用HAL层的module,这种调用方式没有经过封装,上层直接操作底层的硬件设备,在编译时会调用到。但其明显的缺点是接口不统一,如果出现多个进程同时调用,由于需要对各进程空间进行映射会造成存储空间的浪费,同时存在代码的安全输人问题,容易造成系统崩溃。
  libhardware架构中HAL层使用的是HAL module和HAL stub结合形式,Stub以动态链接库的方式存在。就操作而言,HAL层实现对库的隐藏。Android系统的HAL层包含很多的Stub,采用统一的调用方式对硬件进行操作。上层在HAL层调用Stub的函数,然后再回调这些操作函数。通过这样的模式,实现接口统一,而且各Stub没有关系,上层若要对某个硬件设备进行操作只要提供模块ID,就能对相关设备进行操作。HAL stub不是一个共享库,在编译时上层只拥有访问 HAL stub 的函数指针,并不需要 HAL stub。在上层通过HAL module 提供的统一接口获取并操作 HAL stub,所以文件只会被映射到一个进程而不会存在重复映射和重入问题。
  从现在HAL层的结构可以看出,当前的HAL stub模式是一种代理人 (proxy)的概念,虽然stub仍以*.so文件的形式存在,但是HAL已经将*.so文件隐藏了。stub向HAL提供了功能强大的操作函数(Operations),而Runtime则从HAL获取特定模块(stub)的函数,然后再回调这些操作函数。这种以Indirect Function Call模式的架构,让HAL stub变成了一种“包含”关系也就是说在HAL里面包含了许多 stub(代理人)。Runtime只要说明module ID(类型)就可以取得操作函数。在当前的HAL模式中,Android 定义了HAL层结构框架,这样通过接口访问硬件时就形成了统一的调用方式。下图直观展示旧架构和新架构的不同之处:
在这里插入图片描述

  HAL stub不是一个共享库,在编译时上层只拥有访问 HAL stub 的函数指针,并不需要 HAL stub。在上层通过HAL module 提供的统一接口获取并操作 HAL stub,所以文件只会被映射到一个进程而不会存在重复映射和重入问题。

3. HAL module的架构分析

  Android 7的HAL采用HAL module和HAL stub结合的形式进行架构,HAL stub不是一个ShareLibrary(共享程序),在编译时上层只拥有访问HAL stub的函数指针并不需要HAL stub。上层通过HAL module提供的统一接口获取并操作HAL stub,so文件只会被mapping到一个进程,也不存在重复mapping和重入问题。

HAL module架构主要分为以下3个结构体:

  • struct hw_module_t
  • struct hw_module_methods_t
  • struct hw_device_t

  以上3个抽象概念在文件 hardware/libhardware/include/hardware/hardware.h 中进行了具体描述。对于不同的hardware的HAL,对应的lib命名规则是d.variant.so,例如:gralloc.msm7k.so 表示其id是gralloc,msm7k是variant。variant的取值范围是在该文件中定义的variant keys对应的值。

3.1 hw_module_t

/**
 * Every hardware module must have a data structure named HAL_MODULE_INFO_SYM
 * and the fields of this data structure must begin with hw_module_t
 * followed by module specific information.
 */
typedef struct hw_module_t {
    /** tag must be initialized to HARDWARE_MODULE_TAG */
    uint32_t tag;

    /**
     * The API version of the implemented module. The module owner is
     * responsible for updating the version when a module interface has
     * changed.
     *
     * The derived modules such as gralloc and audio own and manage this field.
     * The module user must interpret the version field to decide whether or
     * not to inter-operate with the supplied module implementation.
     * For example, SurfaceFlinger is responsible for making sure that
     * it knows how to manage different versions of the gralloc-module API,
     * and AudioFlinger must know how to do the same for audio-module API.
     *
     * The module API version should include a major and a minor component.
     * For example, version 1.0 could be represented as 0x0100. This format
     * implies that versions 0x0100-0x01ff are all API-compatible.
     *
     * In the future, libhardware will expose a hw_get_module_version()
     * (or equivalent) function that will take minimum/maximum supported
     * versions as arguments and would be able to reject modules with
     * versions outside of the supplied range.
     */
    uint16_t module_api_version;
#define version_major module_api_version
    /**
     * version_major/version_minor defines are supplied here for temporary
     * source code compatibility. They will be removed in the next version.
     * ALL clients must convert to the new version format.
     */

    /**
     * The API version of the HAL module interface. This is meant to
     * version the hw_module_t, hw_module_methods_t, and hw_device_t
     * structures and definitions.
     *
     * The HAL interface owns this field. Module users/implementations
     * must NOT rely on this value for version information.
     *
     * Presently, 0 is the only valid value.
     */
    uint16_t hal_api_version;
#define version_minor hal_api_version

    /** Identifier of module */
    const char *id;

    /** Name of this module */
    const char *name;

    /** Author/owner/implementor of the module */
    const char *author;

    /** Modules methods */
    struct hw_module_methods_t* methods;

    /** module's dso */
    void* dso;

#ifdef __LP64__
    uint64_t reserved[32-7];
#else
    /** padding to 128 bytes, reserved for future use */
    uint32_t reserved[32-7];
#endif

} hw_module_t;

  在结构体 hw_module_t中,需要注意如下5点:

  1. 在结构体hw_module_t 的定义前面有一段注释,意思是,硬件抽象层中的每一个模块都必须自定义一个硬件抽象层模块结构体,而且它的第一个成员变量的类型必须为 hw_module_t 。
  2. 硬件抽象层中的每一个模块都必须存在一个导出符号HAL_MODULE_IFNO_SYM,即HMI,它指向一个自定义的硬件抽象层模块结构体。后面在分析硬件抽象层模块的加载过程时,将会看到这个导出符号的意义。
  3. 结构体 hw_module_t 的成员变量 tag 的值必须设置为 HARDWARE_MODULE_TAG,即设置为一个常量值(‘H’<<24 | ‘W’<<16 | ‘M’<<8 | ‘T’),用来标志这是一个硬件抽层模块结构体。
  4. 结构体 hw_module_t 的成员量 dso 用来保存加硬抽象层模块后得到的句柄值。前面提到,每一个硬件抽象层模块都对应有一个动态链接库文件。加载硬件抽象层模块的过程实际上就是调用 dlopen() 函数来加载与其对应的动态链接库文件的过程。在调用 dlclose() 函数来卸载这个硬件抽象层模块时,要用到这个句柄值,因此,在加载时需要将其保存起来。
  5. 结构体 hw_module_t的成员变量 methods 定义了一个硬件抽象层模块的操作方法列表,其类型为hw_module_methods_t 。

3.2 hw_module_methods_t

typedef struct hw_module_methods_t {
    /** Open a specific device */
    int (*open)(const struct hw_module_t* module, const char* id,
            struct hw_device_t** device);

} hw_module_methods_t;

  在结构体 hw_module_methods_t 中只有一个成员,它是一个函数指针,用来打开硬件抽象层模块中的硬件设备。由于一个硬件抽象层模块可能会包含多个硬件设备,因此在调用结构体 hw_module_methods_t 的成员量open,打开一个硬件设备时需要指定其ID。其中:

  • 参数 module :表示要打开的硬件设备所在的模块。
  • 参数 id :表示要打开的硬件设备的ID。
  • 参数 device :是一个输出参数,用来描述一个已经打开的硬件设备。

3.3 hw_device_t

/**
 * Every device data structure must begin with hw_device_t
 * followed by module specific public methods and attributes.
 */
typedef struct hw_device_t {
    /** tag must be initialized to HARDWARE_DEVICE_TAG */
    uint32_t tag;

    /**
     * Version of the module-specific device API. This value is used by
     * the derived-module user to manage different device implementations.
     *
     * The module user is responsible for checking the module_api_version
     * and device version fields to ensure that the user is capable of
     * communicating with the specific module implementation.
     *
     * One module can support multiple devices with different versions. This
     * can be useful when a device interface changes in an incompatible way
     * but it is still necessary to support older implementations at the same
     * time. One such example is the Camera 2.0 API.
     *
     * This field is interpreted by the module user and is ignored by the
     * HAL interface itself.
     */
    uint32_t version;

    /** reference to the module this device belongs to */
    struct hw_module_t* module;

    /** padding reserved for future use */
#ifdef __LP64__
    uint64_t reserved[12];
#else
    uint32_t reserved[12];
#endif

    /** Close this device */
    int (*close)(struct hw_device_t* device);

} hw_device_t;

  在结构体hw_device_t中,需要注意如下3点:

  1. 硬件抽象层模块中的每一个硬件设备都必须自定义一个硬件设备结构体,而且它的第一个成员变量的类型必须为 hw_device_t 。
  2. 结构体 hw_device_t 的成员变量 tag 的值必须设置为HARDWARE_DEVICE_TAG,即设置为个常量值(‘H’<<24 | ‘W’<<16 | ‘M’<<8 | ‘T’),用来标志这是一个硬件抽象层中的硬件设备结构体。
  3. 结构体 hw_device_t 的成员变量 close 是一个函数指针,用来关闭一个硬件设备。

4. 分析hardware.c

5. 分析HAL的加载过程

6. 分析硬件访问服务

7. 官方实例mokoid分析

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

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

相关文章

HDFS集群部署成功但网页无法打开如何解决(显示配置通过浏览器访问hdfs的端口)

在学习黑马2023大数据教程过程中&#xff0c;首先依照视频完成了如下配置&#xff1a;【必须】 【黑马2023大数据实战教程】大数据集群环境准备过程记录&#xff08;3台虚拟机&#xff09; 黑马2023大数据实战教程】VMWare虚拟机部署HDFS集群详细过程 最后node1的hadoop用户下…

共建智能汽车数据管理方案 | 4.15 IoTDB X EMQ 主题 Meetup 回顾

4 月 15 日&#xff0c;IoTDB X EMQ 智能汽车主题 Meetup 在上海成功举办。工业物联网时序数据库研发商天谋科技、物联网数据基础设施软件供应商 EMQ 的两位技术大牛&#xff0c;深度分享了企业如何应对智能汽车制造、智慧汽车联网平台普遍面临的海量车况、车产数据“采、存、取…

2023年Chat GPT 应用前景分析

从2022年12月初刚上线至今&#xff0c;不到半年时间ChatGPT月活就超过了1亿用户&#xff01;可谓火的一塌糊涂&#xff0c;比尔盖茨都称&#xff1a;ChatGPT的历史意义重大&#xff0c;不亚于PC或互联网诞生。以至于ChatGPT官网长期都处于满负荷运转的状态&#xff01; 由于Ch…

S7-200 SMART 和 S7-1200PLC进行PROFINET IO通信

从 S7-200 SMART V2.5 版本开始,S7-200 SMART 开始支持做 PROFINET IO 通信的智能设备。因此,两个 S7-200 SMART 之间可以进行 PROFINET IO 通信,一个CPU 作PROFINET IO 控制器,一个 CPU 作 PROFINET 通信的设备。组态的时候有两种方法,一种是通过硬件目录组态另外一种是通…

008+limou+CSS|CSS简介

1、CSS简介 &#xff08;1&#xff09;CSS是什么 指的是“Cascading Style Sheet&#xff08;层叠样式表&#xff09;”&#xff0c;是用来控制网页外观的一门技术 &#xff08;2&#xff09;CSS和CSS3 CSS历经CSS1.0、CSS2.0、CSS2.1、CSS3.0这几个版本&#xff0c;这几个…

java企业级信息系统开发学习笔记07 基于java配置方式使用Spring MVC

文章目录 一、学习目标二、基于java配置方式使用Spring MVC&#xff08;一&#xff09;创建Maven项目&#xff08;二&#xff09;添加相关依赖&#xff08;三&#xff09;创建日志属性文件&#xff08;四&#xff09;创建首页文件&#xff08;五&#xff09;创建Spring MVC配置…

学会Spring Batch 批处理框架,效率翻倍,上班轻松又快乐

一、SpringBatch 介绍 Spring Batch 是一个轻量级、全面的批处理框架&#xff0c;旨在支持开发对企业系统的日常操作至关重要的健壮的批处理应用程序。Spring Batch 建立在人们期望的 Spring Framework 特性&#xff08;生产力、基于 POJO 的开发方法和一般易用性&#xff09;…

uniapp-TypeError: Cannot convert undefined or null to object

问题详情 INFO Starting development server...ERROR TypeError: Cannot convert undefined or null to object TypeError: Cannot convert undefined or null to objectat Function.assign (<anonymous>)at uniapp-cli\node_modules\dcloudio\vue-cli-plugin-uni\lib…

Java EE企业级应用开发(SSM)第7章

第7章Spring MVC拦截器 一.预习笔记 1.拦截器是一个运行在服务器端的程序&#xff0c;主要用于拦截用户的请求并进行相应的处理&#xff0c;即实现对控制器请求的预处理或后处理 2.拦截器的实现 2-1&#xff1a;实现Spring的HandlerInterceptor接口 2-2&#xff1a;实现Spri…

基于html+css的图片展示17

准备项目 项目开发工具 Visual Studio Code 1.44.2 版本: 1.44.2 提交: ff915844119ce9485abfe8aa9076ec76b5300ddd 日期: 2020-04-16T16:36:23.138Z Electron: 7.1.11 Chrome: 78.0.3904.130 Node.js: 12.8.1 V8: 7.8.279.23-electron.0 OS: Windows_NT x64 10.0.19044 项目…

Activiti的基本使用

目录 1、Activiti使用 1.1、数据库支持 1.2、Activiti环境 1.2.1、引入依赖 1.2.2、添加配置 1.2.3、启动项目 1.2.4、数据库表介绍 1.3、Activiti常用Service服务接口 1.4、流程设计工具 1.4.1、下载activiti-explorer 1.4.2、解压获取部署包 1.4.3、部署activiti…

mysql的启动关闭原理和实战,及常见的错误排查

前言 MySQL是一个关系型数据库管理系统&#xff0c;由瑞典MySQL AB 公司开发&#xff0c;属于 Oracle 旗下产品。MySQL是最流行的关系型数据库管理系统之一&#xff0c;在 WEB 应用方面&#xff0c;MySQL是最好的 RDBMS (Relational Database Management System&#xff0c;关系…

【数据结构】顺序表和链表(上)(附leetcode练习题)

☃️个人主页&#xff1a;fighting小泽 &#x1f338;作者简介&#xff1a;目前正在学习C语言和数据结构 &#x1f33c;博客专栏&#xff1a;数据结构 &#x1f3f5;️欢迎关注&#xff1a;评论&#x1f44a;&#x1f3fb;点赞&#x1f44d;&#x1f3fb;留言&#x1f4aa;&…

春秋云境:CVE-2022-30887(文件上传漏洞)

目录 一.题目 二.蚁剑方式 三.POC方式 一.题目 该CMS中php_action/editProductImage.php存在任意文件上传漏洞&#xff0c;进而导致任意代码执行。 进入页面&#xff1a;登录页面 随意输入用户名和密码&#xff1a;admingmail.com admin 用于burp抓包&#xff1a; burp抓包…

基于PCL抓取Velodyne激光雷达数据包可视化

Velodyne 高清激光雷达 (HDL) 采集器 Velodyne HDL 是一种基于网络的 3D LiDAR 系统&#xff0c;每秒生成包含超过 700,000 个点的 360 度点云。 PCL 中提供的 HDL Grabber 模仿其他 Grabbers&#xff0c;使其几乎可以即插即用。 然而&#xff0c;由于 HDL 设备是基于网络的&…

线性表总结

线性表 目录&#xff1a; 文章目录 线性表概念一、线性表的定义二、线性表的基本操作三、线性表的实现方式四、线性表的应用总结 概念 线性表是一种基本的数据结构&#xff0c;由一系列具有相同类型的数据元素构成&#xff0c;这些元素之间具有线性的顺序关系&#xff0c;每个…

python+vue+django旅游景点酒店线路套餐管理系统

1.查询旅游信息:主要查询景点和酒店的信息&#xff0c;可以进行分类查询也可以用关键在字来查询用户需要的信息。 2.留言功能:用户可以查看别人以前的留言&#xff0c;也可以发表新的留言。. 3.酒店预定:当用户查询到相关酒店&#xff0c;并且可以能够申请相关酒店预定。 4.信息…

【人工智能】— 一阶逻辑、量词的推理规则、一般化分离规则、合一、前向/反向链接算法、归结算法

这里写自定义目录标题 量词的推理规则全称量词实例化存在量词实例化 简化到命题逻辑推理Generalized Modus Ponens&#xff08;一般化分离规则&#xff09;举例 合一Forward chaining 前向链接算法示例 Backward chaining algorithm 反向链接算法一般FOL的FC/BC的完整性 归结算…

系统分析师选择题笔记

目录 1、知识产权与标准化 1.1 保护范围与对象(★★★★) 1.2 保护期限(★) 1.3 知识产权人确定(★★★) 1.4 侵权判断(★★★) 1.5 标准的分类(★) 1.6 标准代号的识别(★) 2、系统配置与性能评价 2.1 系统性能概述 2.2 系统性能&#xff08;性能指标&#xff09;(★…

8款数据迁移工具选型,主流且实用

前言&#xff1a;ETL(是Extract-Transform-Load的缩写&#xff0c;即数据抽取、转换、装载的过程)&#xff0c;对于企业应用来说&#xff0c;我们经常会遇到各种数据的处理、转换、迁移的场景。今天特地给大家汇总了一些目前市面上比较常用的ETL数据迁移工具&#xff0c;希望对…