HAL so库加载机制---之一
来源:互联网 发布:javascript中文手册 编辑:程序博客网 时间:2024/05/29 08:28
1,概述
Android HAL(Hardware Abstract Layer)硬件抽象层,从字面意思可以看出是对硬件设备的抽象和封装,
为Android在不同硬件设备提供统一的访问接口。HAL处于Android framework和Linux kernel driver之间,
HAL存在的意义有以下2个方面:
1,HAL屏蔽了不同硬件设备的差异,为Android提供了统一的访问硬件设备的接口。
不同的硬件厂商遵循HAL标准来实现自己的硬件控制逻辑,但开发者不必关心不同硬件设备的差异,
只需要按照HAL提供的标准接口访问硬件就可以了。
2,HAL层帮助硬件厂商隐藏了设备相关模块的核心细节。硬件厂商处于利益考虑,不希望公开硬件设备相关的实现细节;
有了HAL层之后,他们可以把一 些核心的算法之类的东西的实现放在HAL层,而HAL层位于用户空间,不属于linux内核,
和android源码一样遵循的是Apache license协议,这个是可以开源或者不开的。
搞清楚了HAL存在的作用,就可以对其框架做个简单的总结。这里从以下3个方面来简单分析下HAL架构.
1,分析HAL的2个核心数据结构:hw_module_t 和 hw_device_t;
2,描述HAL是如何查询和加载设备动态共享库的;
3,以GPS为例,简单分析上层是如何使用HAL来访问硬件设备的。
本文基于android 6.0。
2, 数据结构
hw_module_t结构体:Android HAL将各类硬件设备抽象为硬件模块,HAL使用该结构体描述一类硬件抽象模块。
每个硬件抽象模块都对应一个动态链接库,一般是由厂商提供的,这个动态链接库必须尊重HAL的命名规范才能被HAL加载到,后面会看到。
hw_device_t结构体:每一类硬件抽象模块又包含多个独立的硬件设备,HAL使用该结构体描述硬件模块中的独立硬件设备。
2.1 hw_module_t
hardware.h文件中的hw_module_t结构体定义如下,
typedef struct hw_module_t {uint32_t tag;uint16_t module_api_version;#define version_major module_api_versionuint16_t hal_api_version;#define version_minor hal_api_versionconst char *id;const char *name;const char *author;struct hw_module_methods_t* methods;void* dso;#ifdef __LP64__ uint64_t reserved[32-7];#elseuint32_t reserved[32-7];#endif} hw_module_t;
注意:
1, 每个硬件模块必须包含一个名字为HAL_MODULE_INFO_SYM的结构体;
这个结构体的第一个元素必须为hw_module_t,然后后面可以增加模块相关的其他信息。
这里可以理解为是一种继承关系,相当于应硬件模块的HAL_MODULE_INFO_SYM结构体,继承了hw_module_t,
只不过是C语言中没有继承的概念,是通过在结构体中包含的方式间接实现的。
HAL_MODULE_INFO_SYM值定义同样在hardware.h中:
#define HAL_MODULE_INFO_SYM HMI#define HAL_MODULE_INFO_SYM_AS_STR "HMI"
2, tag必须被初始化HARDWARE_MODULE_TAG常量,其定义如下,
#define MAKE_TAG_CONSTANT(A,B,C,D) (((A) << 24) | ((B) << 16) | ((C) << 8) | (D))#define HARDWARE_MODULE_TAG MAKE_TAG_CONSTANT('H', 'W', 'M', 'T')#define HARDWARE_DEVICE_TAG MAKE_TAG_CONSTANT('H', 'W', 'D', 'T')
3,dso:用来保存加载硬件抽象模块后得到的句柄值,前面提到每一个硬件抽象模块都对应一个动态链接库,
硬件抽象模块的加载过程实际是使用dlopen函数打开对应的动态链接库文件获得这个句柄;
使用dlclose函数进行硬件抽象模块的卸载是需要用到这个句柄,因此需要保存起来。
4, hw_module_methods_t结构体方法定义如下,
typedef struct hw_module_methods_t { int (*open)(const struct hw_module_t* module, const char* id, struct hw_device_t** device);} hw_module_methods_t;
该结构体只有一个函数指针open,打开硬件模块获取模块中的硬件设备。由于一个硬件抽象模块中可能包含多个设备,
因此需要根据传入的设备id来获取相应的硬件设备he_device_t。所以这里的device就表示一个已经打开的硬件设备。
2.2 hw_device_t
hardware.h文件中的hw_device_t结构体定义如下,
typedef struct hw_device_t { uint32_t tag; uint32_t version;struct hw_module_t* module;#ifdef __LP64__ uint64_t reserved[12];#else uint32_t reserved[12];#endif int (*close)(struct hw_device_t* device);} hw_device_t;
module:表示该硬件设备归属于哪一个硬件抽象模块。
close:函数指针,用来关闭硬件设备。
小结:到此,HAL的2个核心数据结构体就分析完了;硬件厂商必须遵循HAL规范和命名,实现hw_module_t结构体;
并且提供open函数来获取hw_device_t。下面看看HAL到底是怎样获取硬件模块和硬件设备的,是如何加载和解析对应的动态共享库的。
3, HAL库规范
HAL会按照variant_keys[]定义的属性名称的顺序逐一来读取属性值,若值存在,
则作为variant的值加载对应的动态链接库。如果没有读取到任何属性值,
则使用<MODULE_ID>.default.so 作为默认的动态链接库文件名来加载硬件模块。
hardware.c文件中的variant_keys定义如下,
static const char *variant_keys[] = { "ro.hardware", /* This goes first so that it can pick up a different file on the emulator. */ "ro.product.board", "ro.board.platform", "ro.arch"};
variant_keys中模块名个数,逐个查找。
static const int HAL_VARIANT_KEYS_COUNT = (sizeof(variant_keys)/sizeof(variant_keys[0]));
有了模块的文件名字规范,那么共享库的存放路径也是有规范的。HAL规定了2个硬件模块动态共享库的存放路径,
#if defined(__LP64__)#define HAL_LIBRARY_PATH1 "/system/lib64/hw"#define HAL_LIBRARY_PATH2 "/vendor/lib64/hw"#else#define HAL_LIBRARY_PATH1 "/system/lib/hw"#define HAL_LIBRARY_PATH2 "/vendor/lib/hw"#endif
也就是说硬件模块的共享库必须放在/system/lib/hw 或者 /vendor/lib/hw 这2个路径下的其中一个。
HAL在加载所需的共享库的时候,会先检查HAL_LIBRARY_PATH2路径下面是否存在目标库;
如果没有,继续检查HAL_LIBRARY_PATH1路径下面是否存在。具体实现在hw_module_exists方法中,如下,
static int hw_module_exists(char *path, size_t path_len, const char *name, const char *subname){ snprintf(path, path_len, "%s/%s.%s.so", HAL_LIBRARY_PATH2, name, subname); if (access(path, R_OK) == 0) return 0; snprintf(path, path_len, "%s/%s.%s.so",HAL_LIBRARY_PATH1, name, subname); if (access(path, R_OK) == 0) return 0; return -ENOENT;}
name:其实对应上面提到的MODULE_ID
subname: 对应从上面提到的属性值variant
- HAL so库加载机制---之一
- HAL so库加载机制---之二
- 安卓HAL层 so库文件加载原理
- Android框架之Camera(2)HAL及so库的加载
- android 插件加载机制之一
- Android加载so库
- 加载so库
- 动态加载so库
- 北斗gps Android hal层so库代码
- 北斗gps Android hal层so库代码
- so 动态加载库 Hotpatch
- android动态加载so库
- Android Native 库.so加载
- android so 库加载问题
- so 库加载 __attribute__((constructor))
- 动态加载so库文件
- so 库的动态加载
- 动态加载so库文件
- ubuntu ssh配置 + xshell
- 500万条微博数据来源分析
- 《高质量编程指南》笔记1
- 每个熊孩子背后都站着一对熊父母
- 阿里云服务器Tomcat、nginx无法访问——端口问题
- HAL so库加载机制---之一
- T
- 程序员面试金典——元素查找_____
- 欢迎使用CSDN-markdown编辑器
- 不可变类
- Unity3d shader 学习笔记
- Host SMBus controller not enabled
- [LeetCode]26. Remove Duplicates from Sorted Array
- 洛谷OJ