Android系统从宏观上可以看成一个图形系统,类似于QT,迷你GUI等开源的图形用户界面系统。但是android作为手机软件包,它还具有很多的其他功能是QT、MINIGUI不具备的,比如电话、定位、WIFI、sensor、摄像头等功能。Android集成了很多开源的代码,我们只需要在Linux层做好硬件的驱动程序剩下的很多软件开发工作android都是做好了的。烧写过手机固件的都知道,android的固件大概有uboot.img、boot.img(包含ramdisk和kernel),system.img,cache.img,userdata.img等。下面是一张android启动流程图,来自网络。

其中system.img可以理解为android的本体部分。

System.img最终会挂在ramdisk的/system目录下面,其内容说明如下:

system/app     这个里面主要存放的是常规下载的应用程序,可以看到都是以APK格式结尾的文件。在这个文件夹下的程序为系统默认的组件,自己安装的软件将不会出现在这里,而是/data/文件夹中。

system/bin       这个目录下的文件都是系统的本地程序,从bin文件夹名称可以看出是binary二进制的程序,里面主要是Linux系统自带的组件。

system/etc       从文件夹名称来看保存的都是系统的配置文件,比如APN接入点设置等核心配置。

system/fonts   字体文件夹,除了标准字体和粗体、斜体外可以看到文件体积最大的可能是中文字库,或一些unicode字库。

system/framework  主要是一些核心的文件,从后缀名为jar可以看出是是系统平台框架。

 system/lib       lib目录中存放的主要是系统底层库,如hardware层库。

system/media  铃声音乐文件夹,除了常规的铃声外还有一些系统提示事件音

system/usr      用户文件夹,包含共享、键盘布局、时间区域文件等。

现在android编译的结果呈现在上面,从功能逻辑上android的结构是这样的:

Android的一些库的运行是依赖硬件的,但是为了让android与Linux隔离开,硬件抽象层扮演了和驱动层打交道的角色,也扮演了BSP开发应用层部分的工作。有了hardware和kernel的配合,android才能稳定的运行在目标板上。

在"/system/lib/hw"下面定义了硬件抽象层编译的动态库文件。动态库文件可以理解为厨师的各类厨具,需要就颠一下,不需要就放在那儿。那么hardware层的库文件是怎么为其他库提供支持的呢?比如android的APP应用程序现在要把一幅图显示到LCD上,就需要硬件驱动的支持,APP会通过控件调用framework层的libui库,libui库根据ID号选调hardware层的动态库"/system/lib/hw/gralloc.*.so",然后硬件抽象层再继续调用驱动层的接口/dev/fb0。

Tips:

framework层调用函数hw_get_module依次在目录/system/lib/hw和/vendor/lib/hw中检查是否存在以下四个文件:

      gralloc.<ro.hardware>.so

      gralloc.<ro.product.board>.so

      gralloc.<ro.board.platform>.so

      gralloc.<ro.arch>.so
    只要其中的一个文件存在,  函数hw_get_module就会停止查找过程,并且调用另外一个函数load来将这个文件加载到内存中来。另一方面,如果在/system/lib/hw和/vendor/lib/hw中均不存这些文件,那么函数hw_get_module就会在目录/system/lib/hw中查找是否存在一个名称为gralloc.default.so的文件。

硬件抽象层调用关系(架构图):

Android硬件抽象层规定了一个框架,集中体现在某个模块的头文件的实现。以hardware\libhardware\include\hardware\gralloc.h为例(精简版):

/**

* The id of this module

*/

#define GRALLOC_HARDWARE_MODULE_ID"gralloc"

/**

* Name of the graphics device to open

*/

#defineGRALLOC_HARDWARE_FB0 "fb0"

#defineGRALLOC_HARDWARE_GPU0 "gpu0"

/**

* Every hardware module must have a datastructure named HAL_MODULE_INFO_SYM

* and the fields of this data structure mustbegin with hw_module_t

* followed by module specific information.

*/

typedef struct gralloc_module_t {

   struct hw_module_t common;

int (*registerBuffer)(structgralloc_module_t const* module,

buffer_handle_t handle);

int(*unregisterBuffer)(struct gralloc_module_t const* module,

buffer_handle_t handle);

int(*lock)(struct gralloc_module_t const* module,

buffer_handle_t handle, int usage,

int l, int t, int w, int h,

void** vaddr);

int(*unlock)(struct gralloc_module_t const* module,

buffer_handle_t handle);

/* reserved for future use */

int (*perform)(struct gralloc_module_tconst* module,

int operation, ... );

/* reserved for future use */

void* reserved_proc[7];

}gralloc_module_t;

/**

* Every device data structure must begin withhw_device_t

* followed by module specific public methodsand attributes.

*/

typedef struct framebuffer_device_t {

   struct hw_device_t common;

/* flags describing some attributes of theframebuffer */

const uint32_t  flags;

/* dimensions of the framebuffer in pixels*/

const uint32_t  width;

const uint32_t  height;

/* frambuffer stride in pixels */

const int       stride;

/* framebuffer pixel format */

const int      format;

/* resolution of the framebuffer's displaypanel in pixel per inch*/

const float     xdpi;

const float     ydpi;

/* framebuffer's display panel refresh ratein frames per second */

const float     fps;

/* min swap interval supported by thisframebuffer */

const int       minSwapInterval;

/* max swap interval supported by thisframebuffer */

const int       maxSwapInterval;

int reserved[8];

int (*setSwapInterval)(structframebuffer_device_t* window,

int interval);

int (*setUpdateRect)(structframebuffer_device_t* window,

int left, int top, int width, intheight);

int (*post)(struct framebuffer_device_t*dev, buffer_handle_t buffer);

int (*compositionComplete)(structframebuffer_device_t* dev);

void* reserved_proc[8];

}framebuffer_device_t;

1、     每一个hardware硬件模块都有一个ID;

2、     每一个hardware模块必须有一个继承struct hw_module_t common;的结构体;

3、     每一个hardware模块必须有一个继承struct hw_device_t common;的结构体;

structhw_module_t的继承者担负了“联络员”的任务,在/system/lib/hw下面有若干了hardware module,本地框架层通过ID找到对应的模块。

structhw_device_t的继承者承担了对驱动操作方法的包装的任务。

structhw_module_t和struct hw_device_t的内容定义在hardware\libhardware\include\hardware\hardware.h如下:

/**

* Every hardware module must have a datastructure named HAL_MODULE_INFO_SYM

* and the fields of this data structure mustbegin with hw_module_t

* followed by module specific information.

*/

typedef struct hw_module_t {

/** tag must be initialized toHARDWARE_MODULE_TAG */

uint32_t tag;

/** major version number for the module */

uint16_t version_major;

/** minor version number of the module */

uint16_t version_minor;

/** 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;

/** padding to 128 bytes, reserved forfuture use */

uint32_t reserved[32-7];

}hw_module_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;

/**

* Every device data structure must begin withhw_device_t

* followed by module specific public methodsand attributes.

*/

typedef struct hw_device_t {

/** tag must be initialized toHARDWARE_DEVICE_TAG */

uint32_t tag;

/** version number for hw_device_t */

uint32_t version;

/** reference to the module this devicebelongs to */

struct hw_module_t* module;

/** padding reserved for future use */

uint32_t reserved[12];

/** Close this device */

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

}hw_device_t;

到此我们总结一下硬件具体的调用流程,也是hardware层的工作流程:

1、        通过ID找到硬件模块,structhw_module_t common的结构体的继承者;

2、        通过硬件模块找到hw_module_methods_t,打开操作,获得设备的hw_device_t;

3、        调用hw_device_t中的各种操作硬件的方法;

4、        调用完成,通过hw_device_t的close关闭设备。

下面是一个hardware层的helloworld的例子,目的是了解其原理,也为阅读androidHAL源码提供一个范本。

进入到在hardware/libhardware/include/hardware目录,新建hello.h文件:

#ifndefANDROID_HELLO_INTERFACE_H

#defineANDROID_HELLO_INTERFACE_H

#include<hardware/hardware.h>

__BEGIN_DECLS

/*定义模块ID*/

#defineHELLO_HARDWARE_MODULE_ID "hello"

/*硬件模块结构体*/

structhello_module_t {

struct hw_module_t common;

};

/*硬件接口结构体*/

structhello_device_t {

struct hw_device_t common;

int fd;

int (*set_val)(struct hello_device_t*dev, int val);

int (*get_val)(struct hello_device_t*dev, int* val);

};

__END_DECLS

#endif

进入到hardware/libhardware/modules目录,新建hello目录,并添加hello.c文件

#defineLOG_TAG "HelloStub"

#include<hardware/hardware.h>

#include<hardware/hello.h>

#include<fcntl.h>

#include<errno.h>

#include<cutils/log.h>

#include<cutils/atomic.h>

/*驱动程序接口/dev/hello*/

#defineDEVICE_NAME "/dev/hello"

#defineMODULE_NAME "Hello"

/*设备打开和关闭接口*/

staticint hello_device_open(const struct hw_module_t* module, const char* name,struct hw_device_t** device);

staticint hello_device_close(struct hw_device_t* device);

/*设备访问接口*/

staticint hello_set_val(struct hello_device_t* dev, int val);

staticint hello_get_val(struct hello_device_t* dev, int* val);

/*模块方法表*/

staticstruct hw_module_methods_t hello_module_methods = {

open: hello_device_open

};

/*模块实例变量*/

structhello_module_t HAL_MODULE_INFO_SYM = {

common: {

tag: HARDWARE_MODULE_TAG,

version_major: 1,

version_minor: 0,

id: HELLO_HARDWARE_MODULE_ID,

name: MODULE_NAME,

author: “mr shao”,

methods:&hello_module_methods,

}

};

static int hello_device_open(const structhw_module_t* module, const char* name, struct hw_device_t** device) {

structhello_device_t* dev;dev = (struct hello_device_t*)malloc(sizeof(structhello_device_t));

if(!dev){

LOGE("HelloStub: failed to alloc space");

return-EFAULT;

}

memset(dev,0, sizeof(struct hello_device_t));

dev->common.tag= HARDWARE_DEVICE_TAG;

dev->common.version= 0;

dev->common.module= (hw_module_t*)module;

dev->common.close= hello_device_close;

dev->set_val= hello_set_val;dev->get_val = hello_get_val;

if((dev->fd= open(DEVICE_NAME, O_RDWR)) == -1) {

LOGE("HelloStub: failed to open /dev/hello -- %s.", strerror(errno));free(dev);

return-EFAULT;

}

*device= &(dev->common);

LOGI("HelloStub: open /dev/hello successfully.");

return0;

}

static int hello_device_close(structhw_device_t* device) {

structhello_device_t* hello_device = (struct hello_device_t*)device;

if(hello_device){

close(hello_device->fd);

free(hello_device);

}

return0;

}

static int hello_set_val(structhello_device_t* dev, int val) {

LOGI("HelloStub: set value %d to device.", val);

write(dev->fd,&val, sizeof(val));

return0;

}

static int hello_get_val(structhello_device_t* dev, int* val) {

if(!val){

LOGE("HelloStub: error val pointer");

return-EFAULT;

}

read(dev->fd,val, sizeof(*val));

LOGI("HelloStub: get value %d from device", *val);

return0;

}

继续在hello目录下新建Android.mk文件:

LOCAL_PATH := $(call my-dir)

include$(CLEAR_VARS)

LOCAL_MODULE_TAGS := optional

LOCAL_PRELINK_MODULE := false

LOCAL_MODULE_PATH:= $(TARGET_OUT_SHARED_LIBRARIES)/hw

LOCAL_SHARED_LIBRARIES := liblog

LOCAL_SRC_FILES:= hello.c

LOCAL_MODULE :=hello.default

include$(BUILD_SHARED_LIBRARY)

注意,LOCAL_MODULE的定义规则,hello后面跟有default,hello.default能够保证我们的模块总能被硬象抽象层加载到。关于Android.mk的用法请参考:

例说如何编译android模块 http://blog.csdn.net/eliot_shao/article/details/50441219

mmm hardware/libhardware/modules/hello

      编译成功后,就可以在out/target/product/generic/system/lib/hw目录下看到hello.default.so文件了。

参考文章:

http://blog.csdn.net/luoshengyang/article/details/6573809

http://blog.csdn.net/eliot_shao/article/details/50441219

http://blog.csdn.net/luoshengyang/article/details/7747932

《Android板级支持与硬件相关子系统》韩超 第二章

linux中的硬件抽象层相关推荐

  1. c linux time微秒_Linux基础知识(Linux系统、Linux中的链表)

    Linux系统简介 Linux系统的结构及特点 Linux系统的结构图如下图所示: 从上图可以看出,Linux是一个典型的宏内核(一体化内核)结构.硬件系统上面时硬件抽象层,在硬件抽象层上面时内核服务 ...

  2. linux中_Linux基础知识(Linux系统、Linux中的链表)

    Linux系统简介 Linux系统的结构及特点 Linux系统的结构图如下图所示: 从上图可以看出,Linux是一个典型的宏内核(一体化内核)结构.硬件系统上面时硬件抽象层,在硬件抽象层上面时内核服务 ...

  3. Linux中_Ubuntu上_使用命令总结整理_02

    文章目录 目录: 1.操作系统操作 1.Linux 基础 2.系统信息 3.系统负载 -- top 4.程序开机自启动服务配置 5.重定向_管道_流 6.终端其他命令 2.文件与目录操作 1.文件和目 ...

  4. c++ 进程快照_如何在 Linux 中找出内存消耗最大的进程

    很多次,你可能遇见过系统消耗了过多的内存.如果是这种情况,那么最好的办法是识别出 Linux 机器上消耗过多内存的进程. -- Magesh Maruthamuthu(作者) 很多次,你可能遇见过系统 ...

  5. linux的tar中ztvf,linux中的tar命令(2)

    实例4:只将 /tar 内的 部分文件解压出来 命令: tar -zxvf /opt/soft/test/log30.tar.gz log2013.log 输出: [root@localhost te ...

  6. centos6.5 php5.2,Linux中PHP安装与配置(CentOS-6.5:php-5.2.13)

    1 PHP简介     PHP(PHP: Hypertext Preprocessor的缩写,中文名:"超文本预处理器")是一种通用开源脚本语言.语法吸收了C语言.Java和Per ...

  7. java 外部类似_[求指点] 如何用java 实现类似linux中管道调用外部程序的功能

    想写个小程序实现类似linux中管道的功能,创建一个外部子进程,然后主进程不断地写输入给子进程,而后把子进程的返回值取出. 如下的小代码就是从stdin读入一个字符串,调用子进程(cat)返回这个串, ...

  8. linux 修改java版本_Linux 有问必答:如何在 Linux 中改变默认的 Java 版本

    提问:当我尝试在Linux中运行一个Java程序时,我遇到了一个错误.看上去像程序编译所使用的Java版本与我本地的不同.我该如何在Linux上切换默认的Java版本? 当Java程序编译时,编译环境 ...

  9. linux ls 命令 路径,使用ls命令在Linux中使用完整路径列出文件

    许多人会发现,这是重复的问题,但我已经经历了所有问题,然后问及这个主题,但没有为我工作.使用ls命令在Linux中使用完整路径列出文件 我想打印使用ls命令的特定文件格式的完整路径名到目前为止,我发现 ...

最新文章

  1. 【Echarts】——上手Demo
  2. strak组件(9):关键字搜索
  3. SAP Spartacus 因为 refresh token 刷新令牌过期后显示用户重新登录页面的逻辑
  4. Linux编程里getopt_long_only函数用法详解
  5. PHP建站环境搭建:汇总网上常见的1键安装包
  6. 盘点世界上最奇怪的6种编程语言
  7. 1-3.Win10系统利用Pycharm社区版安装Django搭建一个简单Python Web项目的步骤之三
  8. 判断是否为两位数(信息学奥赛一本通-T1044)
  9. dubbo 路由配置_Dubbo-go v1.5.1发布,Dubbo 的 Go实现
  10. 【Flutter系列】第一期——初识Dart语言
  11. 求解线性方程组的方法Matlab程序
  12. 推荐一款超快的Android模拟器
  13. yolov5训练自己的数据集并计算mAP
  14. 【入门】Pytorch实现简单的图片分类器
  15. H5 css引入方式 内联样式表
  16. 视频压制参数设置详细说明(转)
  17. 范德堡计算机科学硕士,范德堡大学计算机科学理学硕士研究生申请要求及申请材料要求清单...
  18. java安卓开发工具_Android开发必备那些工具
  19. android如何截屏快捷键是什么手机,安卓截屏快捷键是什么?截屏方法总结 - Android教程 - 安卓中文网...
  20. 台式计算机如何升级,台式电脑怎样升级系统

热门文章

  1. python 输入三个整数x,y,z,请把这三个数由小到大输出。
  2. Hexo博客+ayer主题+部署giteepage
  3. 如何搭建自己的web服务器
  4. TD LTE与FDD LTE 的区别
  5. Icesword 驱动部分分析
  6. PCSX2和GSDX的源代码地址,通过SVN下载。
  7. 清华站gitlab-ce下载太慢,如何本地安装?
  8. java课程设计报告连连看_连连看_java课程设计报告.doc
  9. ubuntu终止进程命令
  10. x1 carbon 扩展屏 模糊