我的Android系统学习笔记——HAL

98 篇文章 1 订阅
73 篇文章 1 订阅

转倒流时光的风车的文章:http://blog.sina.com.cn/s/blog_6a8b794001015jx7.html



我的Android系统学习笔记——HAL

by 蓝终恒

 

一、Android系统通过HAL访问linux驱动的过程

 

1、NativeService通过调用hw_get_module函数获取hw_module_t结构的实例module(获取HALstub);

2、通过modulehw_module_methods_t结构的实例指针methods获得打开具体设备的HALopen方法;

3、HALopen方法的实现中调用C库的open函数打开linux设备文件(获取文件描述符),进而通过其他的文件操作函数实现对设备的控制(此部分可以看作是linux应用编程,注意Androidlibc库与glibc的不同);

 

二、非常重要的三个Android HAL结构

      在Android源码的/hardware/libhardware/include/hardware/hardware.h中定义了三个关键结构体hw_module_t、hw_module_methods_t和hw_device_t,具体结构如下:

 

typedef struct hw_module_t {

      

      uint32_t tag;

 

      

      uint16_t version_major;

 

      

      uint16_t version_minor;

 

      

      const char *id;

 

      

      const char *name;

 

      

      const char *author;

 

      

      struct hw_module_methods_t*methods;

 

      

      void *dso;

 

      

      uint32_t reserved[32 - 7];

}hw_module_t;

 

 

typedef struct hw_module_methods_t {

      

      int (*open)(const struct hw_module_t*module,

const char*id,

structhw_device_t **device);

}hw_module_methods_t;

 

 

typedef struct hw_device_t {

      

      uint32_t tag;

 

      

      uint32_t version;

 

      

      struct hw_module_t*module;

 

      

      uint32_t reserverd[12];

 

      

      int (*close)(struct hw_device_t*device);

}hw_device_t;

 

 

三、HAL stub编程

1、编程思路

(a) 因为Native Service希望获取HALstub,所以应创建一个hw_module_t实例

(b) 因为hw_module_t实例中需要一个hw_module_methods实例的指针,所以在创建hw_module_t实例前应先声明或者创建一个hw_module_methods_t实例;

(c) 因为hw_module_methods_t实例中需要一个HAL的open方法,所以在创建hw_module_methods_t实例前应先声明一个HAL的open方法(实现放在创建hw_module_t实例后);

(d) 实现HAL的open方法,此方法是非常重要的,负责申请结构空间、填充结构成员信息、注册具体API、打开Linux设备(其实打开方法也是个API);

一般它首先声明一个hw_device_t结构指针、为之分配空间并清空所分配的空间,然后填充hw_device_t结构成员信息,其中需要填充一个hw_module_t实例的指针,这是将open方法先声明后实现的原因;因为hw_device_t结构还需要填充一个HAL的close方法,所以在(c)步骤中添加此方法的声明,与open方法“配对”;

观察open方法的形参我们知道可以通过第二个形参向外输出hw_device_t结构指针,这个指针是在实现JNI方法时声明的,我们可以暂不关心,只需要记住它是给上层提供的接口;

以上两步工作完成后,便可在此方法中调用C库的open方法打开Linux设备文件,获取设备文件描述符(HAL接口Kernel的重要步骤),进而添加或调用其他操作Linux设备的方法——C库的文件操作方法即所谓的具体的API(注意AndroidC库与glibc的异同);

(e) 实现Linux设备的其他操作方法,并将声明添加到(c)步骤中

 

2、编程思路拓展

      一般而言,建议在系统底层的编程中也尽量以面向对象的编程思想为指导,所以,我们应该首先将hw_module_t、hw_device_t结构和其他相关的变量、函数封装起来——自定义HAL结构,然后在以上编程思路的基础上稍作改变;其实,这也是HALstub编程所要求的!

 

4、一个led的HALstub编程实例(步骤遵从思路)

//(1)

typedef struct led_module_t {

      struct hw_module_t common;

}led_module_t;

 

typedef struct led_control_device_t {

      struct hw_device_tcommon;

      

      

      int fd;

      int (*set_on)(structled_control_device_t *led_dev, int32_t led_n);

      int (*set_off)(struct led_control_device_t *led_dev, int32_tled_n);

}led_control_device_t;

 

//(2)

 

intled_device_open(const struct hw_module_t *module,

const char*id,

struct hw_device_t**device);

 

intled_device_close(struct hw_device_t *device);

 

 

struct hw_module_methods_t led_module_methods {

      open:led_device_open,

};

 

 

const struct led_module_t HAL_MODULE_INFO_SYM {

      common: {

             tag: HARDWARE_MODULE_TAG,

             version_major: 1,

             version_minor: 0,

             id:LED_HARDWARE_MODULE_ID,

             name: “simple led stub”,

             author: “Lan Zhongheng”,

             methods:&led_module_methods,

},

};

 

 

intled_device_open(const structhw_module_t *module,

const char*id,

struct hw_device_t**device)

{

      led_control_device_t *led_dev;

      led_dev =(led_control_device_t*)malloc(sizeof(led_control_device_t));

      memset(led_dev, 0, sizeof(led_control_device_t));

 

      led_dev->common.tag =HARDWARE_DEVICE_TAG;

      led_dev->common.version = 0;

      led_dev->common.module = module;

      led_dev->common.close = led_device_close;

      

      

      led_dev->set_on =led_on;

      led_dev->set_off = led_off;

 

      led_dev->fd =open(LED_DEVICE, O_RDWR);

      if (led_dev->fd < 0)

             return -1;

 

      *device =&(led_dev->common);

 

      

      //led_off(led_dev, LED1);

      //led_on(led_dev, LED2);

 

      return 0;

}

 

 

……

……

 

      编程时需要我们注意的地方以橙色和红色标识,它们是HAL能够工作的关键;
xxx_module_t结构的实例名称必须为HAL_MODULE_INFO_SYM,这是Android的游戏规则,暂不详解; 

HAL对上层提供接口是通过输出hw_device_t结构指针实现的,在JNI方法的实现中会将此指针强制转换为自定义的xxx_control_device_t(此例是led_control_device_t)结构指针,实现对xxx_control_device_t的fd及方法成员的访问,因此,hw_device_t必须为xxx_control_device_t自定义结构的第一个成员;

 

 

四、补充

 

Android系统的应用层是JAVA,而其kernel是C,Android系统通过JNI方法实现JAVA对C的调用;

历史原因使Android系统有了HAL,它的角色相当于一个中间人,对上层,它负责给JNI提供调用kernel的方法,对下层,它所提供的方法包含能够访问kernel的函数,即kernel提供给上层的API,如:open、read、write、ioctl等;

下面,我们通过对比Android系统架构和Linux系统架构来增加理解:

 我的Android系统学习笔记——HAL

 

Android系统架构(HAL)

 我的Android系统学习笔记——HAL

 

Android系统架构(无HAL)

 我的Android系统学习笔记——HAL

 

Linux系统架构

 

      补充一下基础概念:所谓的API函数,被包含在用户层的函数库中,API对kernel是产生系统调用,对用户程序是提供产生系统调用的方法;所谓的接口,是对外公开声明的函数、变量,即汇编语言中所说的标号或符号,外部程序通过接口可以引用某些自己不具备的服务

 

1、Linux系统架构

Android是基于Linux的扩展,所以我们先来看一下Linux系统架构;

从软件架构的角度来看,Linux分为user层、kernel层,这两层是C实现的(应用层还可用C++实现);

      从系统服务流程的角度来看,Linux有调用服务的user层、执行系统调用的服务层、支持系统调用的内核函数(服务模块);

      所以,在Linux系统中访问设备的流程为:用户层程序直接产生系统调用(系统开发人员)或者通过API函数间接产生系统调用陷入kernel层,在kernel层找到用户程序所需的服务,这里说的是访问设备,则找的是devicedriver,通过devicedriver最终实现对硬件设备的访问;

      以代码示意整个流程:

---------------------------------------------------------------

      

      main()

      {

             operation();

   

 

externsystem_call();
operation()

      {

            system_call();

                                          user层

---------------------------------------------------------------

                                                 kernel层     

 

system_call()

{

       datatype (*system_service)();

       system_service = find_sys_service();

       system_service();

}

 

 

device_operateion()   // this is one of system service modulefunctions(methods)

{

       

}

---------------------------------------------------------------

              device                        硬件层

---------------------------------------------------------------

 

2、Android系统架构

从Android系统架构(无HAL)框图可知,Android系统架构比Linux系统架构多了Application、ApplicationFramework两层,这就是android的应用层(JAVA);

Android将Linux的应用层(用户C程序+函数库)添加一个AndroidRuntime作为其中间层,并将中间层和kernel层统称Android的系统层(C/C++);

HAL所调用的API来自Libraries,真正能和kernel打交道的是API,所以,Android系统架构(HAL)框图并不准确,HAL并非一个独立的具有隔离作用的层,而是从某方面性质上宣称它是一个Layer,其实它相当于Linux系统中的用户C程序组,只是它不仅要完成在Linux系统中用户C程序所要完成的工作,还要向上给JNI提供完成这些工作的接口,实现从JAVA调用C获取kernel系统服务的机制;因此,我个人认为Android系统架构(无HAL)框图更为恰当,HAL的存在只是为了在概念上更好的表述和理解Android系统而已;

Android的整个系统服务调用流程我只从HAL开始往下较为清晰,对JNI方法有初步了解,尚未完全清晰理解,JAVA层则几乎未涉及,此次学习只能暂时到此为止了!

 

学习资源:

http://blog.csdn.net/k229650014/article/details/5801397

http://www.cnblogs.com/armlinux/archive/2012/01/14/2396768.html


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值