有关字符设备驱动的基本概念

编写驱动程序的第一步:定义驱动程序为用户程序提供的能力(机制)!

 

a、模块运行于内核空间

应用程序运行于用户空间

   

b、模块运行时,分配的栈很小,注意栈溢出;

   

c、具有两个下划线前缀(__)的函数,通常是底层组件的接口,需要谨慎使用;

   

d、内核符号表

公共内核符号表用于解释模块内未定义的符号,它包含了所有的全局内核项(函数和变量)

的地址;导出内核符号表加以使用,可以建立模块间的依赖关系(模块层叠技术);

如果一个模块需要向其他模块导出符号:

1 EXPORT_SYMBOL(name);                //(name必须是全局变量)符号可导出
2 EXPORT_SYMBOL_GPL(name);        //符号只供GPL许可证下的模块使用

   

e、所有模块都包含的头文件

1 #include <linux/module.h>        //包含大量函数和符号的定义
2 #include <linux/init.h>                //指定出入口函数
3 #include <linux/moduleparam.h>        //可选:用于定义向模块传递参数的功能

   

f、指定代码许可证

1 MODULE_LICENSE("GPL");

   

g、可使用 #include <linux/errno.h>中定义的错误编码,做函数返回值使用。

   

h、只有系统调用的名字前带有"sys_"前缀

 

Makefile

a、一个源文件

obj-m += src.o

 

b、多个源文件

obj-m += src.o
module-objs := src1.o src1.o

 

c、示例

1 KERN_DIR = /work/system/linux-2.6.22.6
2
3 all:
4         make -C $(KERN_DIR) M=`pwd` modules
5

6 clean:
7         make -C $(KERN_DIR) M=`pwd` modules clean
8
        rm -rf modules.ord
er
9
10 obj-m += src.o 

   

模块的装载与卸载

装载模块:insmod

modprobe

二者区别:modprobe会考虑要装载的模块是否引用了一些当前内核不存在的符号;如果有这类引用,modprobe会在当前模块搜索路径中查找定义了这些符号的其他模块,同时装 载这些模块到内核。

 

卸载模块:rmmod

   

列出当前已装载模块:lsmod

 

insmod *.ko

module_init(fun_init)

1 static int __init fun_init(void)
2 {
3         ......
4 }
5 module_init(fun_init);

 

rmmod *.ko

module_exit(fun_exit);

1 static int __exit fun_exit(void)
2 {
3         ......
4 }
5 module_exit(fun_exit);

 

初始化过程中的错误处理:

①检查函数返回值,确保函数顺利执行;

②出错后,及时撤销已顺利执行的操作(释放已占用内存);

③可以使用goto进行出错处理;

   

   

向模块传递参数

一个设计良好的模块,可以在装载时配置。

 

insmod hellop howmany=10 whom="Mom"

   

定义模块可传入参数的方法:

driver.c

1 ......
2 static char *whom = "world";
3 static int howmany = 1;

4 ......
5 module_param(howmany, int, S_IRUGO);
6 module_param(whom, charp, S_IRUGO);
7 ......

   

支持的参数类型:

(bool, invbool, charp, int, long, short, uint, ulong, ushort)

   

   

以数组的方式传递参数

1 module_param_array(name, type, num, perm);

原文地址:https://www.cnblogs.com/lilto/p/11876797.html