通过第十章的学习,我学到了如下知识点:
1、尽管linux驱动直接与硬件打交道,但并不是linux驱动直接向硬件中的内存写数据,而是本机的I/O内存进行交互。
linux驱动 I/O内存 硬件
2、linux内核的内存管理模块负责同步I/O内存和硬件中的数据。每一个连接linux的硬件在linux内存中都有映射首地址,在使用ioread、iowrite等函数读写I/O内存时,指定这些首地址。
3、硬件在被检查到只说明在内核空间中建立了I/O内存,要想在用户空间程序访问硬件,还必须安装可与I/O内存相互交互的驱动程序。
4、LED驱动提供了两种交互方式:命令和读写设备文件。
5、linux设备文件的设备号分为主设备号和次设备号,其中,前12位表示主设备号,后20位表示次设备号;设备号有两种指定方法:直接在代码中指定和动态分配;
6、尽管在代码中指定设备号比较直观,但如果主设备号和次设备号已经存在,建立设备文件就会失败;
7、多个linux设备文件可以拥有同一个主设备号,但两个设备的主设备号和次设备号不能设置的都一样,使用alloc_chrder_region函数自动分配设备时,baseminor和count参数不要设置太大,否则设备号就会溢出,并且主设备号会进位,从而变成下一个主设备号。int register_chrdev_regionl (dev_t from , unsigned count , const char *name)其中from表示设备号,count表示次设备号范围,name参数表示设备文件名称。
int dev_dev_number=MKDEV(major,minor)
int major =MAJOR(dev_number);
int minor=MAJOR(dev_number);
使用cdev_add函数将字符设备添加到内核中的字符设备文件中。
int cdev_add(struct cdev *p ,dev_t dev, unsigned count){
return kobj_map(cdev _map,dev,count,NULL,exact_match ,exact
_lock,p);
调用cdev_add函数要指定设备文件指针P,设备号(dev)和设备文件数量count,kobj_map负责将设备文件的相关信息添加到保存已建好的设备文件的probes数组中。
8、使用struct class包含了一些与设备文件有关的变量以及一些回调函数的指针变量;
9、卸载linux驱动的设备文件需要依次调用device_destroy,class _destroy和unregister_chrdev_region;
10、LED驱动可以使用两种方式控制LED:通过字符串控制LED;通过I/O命令控制LED;
11、指定一个模板参数需要使用module_param(name,type,perm)宏,
name表示参数名,type表参数类型,perm表示读/写权限。指定模板参数时参数名,参数值,括号间不能有空格;
12、移植linux驱动时,修改linux驱动的源代码应尽量不修改linux的驱动接口。
13、修改模块参数时注意:
a、通过module_param_array宏的第三个参数指定数组长度时要使用指针类型的数据;
b、如果linux驱动包含有多个模块参数,需要将这些参数用单引号或双引号括起来;
c、指定参数类型的参数值时,逗号前后不能有空格。
10.1打印内核调试信息:printk
10.2防止printk函数降低Linux驱动性能
最好的方法是利用C语言中的编译指令
10.3通过虚拟文件系统进行数据交互
10.4调试工具
1.用gdb调试用户空间程序
gdb可以跟踪调试用户空间程序
2.用gdbservice远程调试用户空间程序
3.用kgdb远程调试内核程序
Kgdb包含了两个部分:kgdb的内核和一套连接接口
Kgdb支持多种处理器架构
Kgdb想调试Linux驱动,需要配置Linux内核,使用make menuconfig命令进入linux内核的配置菜单