android深度探索 HAL及驱动开发 第八章

第八章 读书笔记

本章主要讲蜂鸣器的驱动,蜂鸣器是S3cC6410开发板上带的一个硬件设备,本节将介绍蜂鸣器的实现原理,并实现一个完整的蜂鸣器驱动。本节讲介绍把linux驱动分成多个文件的方式。这些文件中的数据结构、函数的代码也可以被多个不同的驱动使用,所以这也是代码重用 的重要方法。Linux代码的重用 重用=静态重用(将要重用的代码放到其他的文件的头文件中声明)+动态重用(使用另外一个Linux驱动中的资源,例如函数、变量、宏等)

1、编译是由多个文件组成的Linux驱动(静态重用)

对于复杂的Linux驱动,需要使用多个源代码文件存放不同的功能代码,这样做有利于代码分类和管理,那么就不得不编译多个源代码文件,最终生成.ko文件或编译进Linux内核

下面,就介绍将3个.c文件分别编译为3个.o文件,并将这3个.o文件链接(link)成一个.ko文件——静态重用

假设C语言源代码文件有main.c、fun.c、product.c、product.h,其中main.c是Linux驱动的主程序,在fun.c和product.c、product.h中定义和实现了在main.c中使用的函数,在main.c中通过extern关键字使用fun.c中的函数,通过包含product.h文件使用product.c文件中的函数

最关键一步就是编写Makefile文件

#Makefile

obj-m := multi_file_driver(文件所在目录).o

multi_file_driver-y := main.o fun.o product.o

总之,c或c++ 语言中编译多个源代码文件时,如果a.c使用了b.c文件中的函数,需要在a.c文件中使用extern预先定义b.c中的函数,extern的作用是告诉编译器该函数的函数名、参数个数、参数类型、返回值类型,等到将a.o和b.o链接成可执行文件或程序库时,编译器再到b.o中寻找函数的具体实现。除此之外,还可以使用b.h文件定义b.c中的函数,然后在a.c中包含b.h文件。

2、Linux驱动模块的依赖(动态重用)

在一个驱动模块里使用另一个驱动模块里的被导出的符号(常量、变量、函数等)

接下来学习了强行卸载linux驱动,只能卸载由于卸载异常情况而导致的linux驱动模块无法卸载的情况。情况1:初始化函数崩溃 2:卸载函数被阻塞

 

蜂鸣器驱动是一个重点,通过相应的寄存器来控制蜂鸣器的打开和关闭,并且在实验蜂鸣器驱动时,将打开和关闭蜂蜜器的函数放到另外的C源代码文件中。PWM驱动由三个文件组成:PWM.C、PWM—fun.h、pwm-fun.c、其中pwm.c是驱动主程序。

本章主要讲了Linux代码的重用与强行卸载Linux驱动。

强行卸载Linux驱动

情况1:初始化函数崩溃

由于Linux驱动模块的初始化函数进行了某些操作而崩溃,从而导致初始化函数无法正常返回,这种情况变现是当前Linux驱动模块没用被任何其他的Linux驱动模块使用,但却显示已经被应用了一次

这种情况关键是引用计数器的值和引用者不一致。只需要将当前的Linux驱动模块的引用计数器清零即可,修改计数器可以使用下面两个函数

//是module指向的Linux驱动模块的引用计数器加1,成功返回1,失败返回0

static inline int try_module_get(struct module *module);

//是module指向的Linux驱动模块的引用计数器减1

extern void module_put(struct module *module);

情况2:卸载函数被阻塞

在使用rmmod命令卸载Linux驱动时,系统会调用卸载函数,只有卸载函数成功返回时,Linux驱动才会被卸载,如果卸载函数被阻塞,rmmod命令也会被阻塞,也就是说永远不会执行到卸载Linux驱动模块的代码,这种情况的表现是一执行rmmod命令就会停在那不动了,永远也不会返回到系统的操作提示符

这种情况的问题根源就是卸载函数,只要将原来的卸载函数替换成一个空的卸载函数即可

总之,两者情况都要解决一个不可回避的问题,就是要获取表示要卸载的Linux驱动模块的module结构体指针。

原文地址:https://www.cnblogs.com/haihaizhazha/p/5626985.html