吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 3061|回复: 1
收起左侧

[会员申请] 申请会员ID:攀登的蜗牛

[复制链接]
吾爱游客  发表于 2016-5-15 23:59
申请标题:申请会员ID:攀登的蜗牛

1、申 请 I D:攀登的蜗牛
2、个人邮箱:kuailedi2015@163.com
3、原创技术文章:Android内核研究之--HAL层学习
注:以帖子内容,可能达不到精华帖,但是本人对热衷内核研究,希望加入到破解论坛与跟多但牛一起交流学习

Android内核学习之番外篇一                                                        -----HAL学习总结与计划1.  学习前言
本篇博客的学习是基于老罗的Android之旅的书和博客的。关于这个地方的学习之前曾经花时间看过一遍,并且跟着走了一遍,但是中途因为碰到问题没有解决,导致很多地方都跳过去了。这一次算是全部走完了整个流程,从底层的驱动编写到顶层app访问虚拟设备成功完整的跟着学习做了一遍。虽然这次也有不少的挫折,但是还好都一一解决了。这里想记录一下学习的过程,并且将后面需要自完善部分也提出来,让自己更深入的理解这一块。
2.  HAL学习编译步骤
(1)    编写Android系统的内核驱动程序
其实内核驱动的编写有一定的格式,只要是有固定格式的编写应该都不难,但是无奈我的C基础比较薄弱,看LDD(Linux Device Drivers)的时候也基本上是囫囵吞枣(这个词我用了好多次,汗颜)了。但是以前一些固定的语法不懂,现在最起码能看懂了。但是能达到编写内核驱动的功力我还是远远不够。只是短期我也没那么多奢求了,只希望能把Android底层摸头就可以了。
这里的驱动并不是为真正的硬件编写,而是为一个虚拟设备----一个4字节的寄存器设备----编写的驱动。
在XXX/kernel/common/drivers 目录下新建驱动文件,按照驱动的格式写好驱动。然后make即可将驱动编译到内核中去。
传统的硬件读写打开关闭方法:
static int hello_open(struct inode* inode, struct file* filp);
static int hello_release(struct inode* inode, struct file* filp);
static ssize_t hello_read(struct file* filp, char __user *buf, size_t count, loff_t* f_pos);
static ssize_t hello_write(struct file* filp, const char __user *buf, size_t count, loff_t* f_pos);
(2)    HAL层模块访问内核驱动程序
按照Android硬件抽象层规范的要求,分别定义模块ID、模块结构体以及硬件接口结构体。
疑问:HAL层的模块是如何同内核的驱动进行交互的,在这里没看明白。
关于这篇文章有个问题没想清楚:这里的HAL模块访问内核驱动,但是是在什么地方涉及到与内核驱动的交互呢?
比如在hello_set_val 方法的实现中,有write(dev->fd, &val, sizeof(val));这样一句代码,这里的write是不是就是对应着HAL系列关于内核驱动编写那篇文章中的   .write =hello_write,也就是这里的write就是调用了内核驱动中hello_write这个方法从而达到HAL模块访问内核驱动模块??
(3)      Runtime Lib层JNI接口访问HAL
通过编写JNI方法,向上层提供jni接口供java访问,方法写在如下的类中:com_android_server_HelloService.cpp
其中包括三个方法:
static void hello_setVal(JNIEnv* env, jobject clazz, jint value)
static jint hello_getVal(JNIEnv* env, jobject clazz)
static jboolean hello_init(JNIEnv* env, jclass clazz)
static const JNINativeMethod method_table[]
int register_android_server_HelloService(JNIEnv *env)
这些方法通过device来调用HAL模块的方法与内核驱动直接交互。
这个类以及类中的方法和类中的变量类型都有严格的命名方式,类名按照com_android_server_XXX方式命名,变量都是按照JNI规定的方式命名变量。
然后在onload.cpp中将JNI的方法注册到内部。
(4)    Frameworks增加硬件访问服务
在下面目录下床架可以与上面的JNI交互的程序:
frameworks/base/core/java/android/os
1.  package android.os;  
2.     
3.  interface IHelloService {  
4.      void setVal(int val);  
5.      int getVal();  
6.  }

首先定义AIDL文件,AIDL是android用来进行远程接口调用的语言模式,android内部可以根据AIDL的定义生成stub类和代{过}{滤}理类,也就是服务端和客户端进程分别可以调用的类,然后这两个类通过binder的机制进行交互通信,也就达到了线程间的通信的目的。
         然后定义一个service继承自stub接口,然后接口的实现通过navtive的方法调用上面所涉及的JNI方法,然后通过JNI方法与内核驱动的交互来访问设备寄存器(我们在上面涉及的虚拟设备)。
这里的AIDL要用hide来标示,否则编译不用过。
(5)    Application层访问frameworks层的硬件服务
1.  helloService = IHelloService.Stub.asInterface(
2.  ServiceManager.getService("hello"));

通过面代码获得上一步注册的HelloService接口,然后在app中调用方法的时候就通过方法中的native访问了运行时层的相关JNI方法,JNI方法通过device调用HAL层的函数与内核模块交互,这样就完成了app==》frameworks==》运行时库==》HAL层模块==》内核驱动==》硬件设备,这一整个过程的流转。
(6)    留白,未完待续……
3. 总结
其实,这个系列虽然是顺利走完了,但是很多内容还是不能融会贯通,我觉得可以通过binder的方式进行改造这个实例,如果改造成功的话说明我算是有个一知半解了,如果改造不成功,那就说明还有很多东西没走通。这个也就是我下面的计划:通过binder的形式改造HAL系列模块,完成从APPèframeworksèRuntime LibèHALè内核驱动è虚拟设备的流转。
看了这么久的资料,自己能整理了一下,感觉硬伤还是很多,主要是自己的积累不够吧。越这样越发佩服这些系列博客的大牛,能定下来学习并整理出这么好的资料给我们指导。我想绝大多数人很难再学得这么深入,有整理出这么高级的材料来了。他们也算是这个方面的巨人了吧。牛顿说他取得那么大的成就是因为站在了巨人笛卡尔的肩上。有人说这是一种谦逊,也有人说这是他在挤兑笛卡尔。但是有一个问题对我等凡人是至关重要的,那就是如何爬上巨人的肩膀上。要想达到一定的高度,只看书只弄懂了还远远不够,还要自己去实践去验证,要牢记知易行难。这样才算是一步一个脚印的往上走。其实经验并不能传授,我们走的更快也仅仅是因为前人的指引下我们少走了很多弯路,但是要达到一个高度只有不断的再弯路中迂回前进,盘旋上升。
继续努力,Keep moving!!!





发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

Hmily 发表于 2016-5-16 11:36

抱歉,未能达到申请要求,申请不通过,可以关注论坛官方微信(吾爱破解论坛),等待开放注册通知。

免费评分

参与人数 1热心值 +1 收起 理由
ASD1518833577 + 1 已答复!

查看全部评分

您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-15 21:26

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表