linux设备驱动
分类
1. 字符设备驱动;
在传递数据时,按照字节流先后顺序传递. (蚂蚁搬家)
例如: LED, 蜂鸣器, 鼠标, 键盘等
2. 块设备;
3. 网络设备;
套路框架如下
假设设备为led
.
1. 驱动三要素
驱动模块加载入口声明:
module_init(led_init);
卸载入口:
module_exit(led_exit);
模块许可声明(必须大写)
MODULE_LICENSE("Dual BSD/GPL");
2. 实现module_init/module_exit对应的函数
3. 添加其他功能模块file_operations
file_operations结构体中的成员函数(都是指针函数),是 驱动与内核的接口, 是用户空间user对linux**系统调用**的最终落实的地方. 因此,这些函数是字符设备驱动程序设计的主要内容.
为了给上层应用提供设备文件的open/write/read/close等基本操作, 在file_operations结构体中先设置好相应的文件操作函数声明,然后具体实现第4步中的硬件控制函数即可.
当应用层在进行系统调用时,由于linux各个用户空间的地址是相互独立的(处于安全的考虑), 内核就会自动根据file_operations的声明调用到驱动相应函数.而不是有应用层直接调用驱动.
4. 硬件地址到内核地址的映射ioremap
为了驱动硬件,实现应用层的期待效果, 需要根据电路板手册编写ARM驱动程序.
只是,这里需要注意的是,由于linux各个用户空间的地址是相互独立的(处于安全的考虑), 因此在这里也需要进行地址转换, 用到的内核提供的接口是ioremap
. 这样就可以实现硬件物理地址到内核虚拟地址空间的映射.
应用层调用驱动的流程.(结合linux软件层次)
- 首先系统调用.syscall
- 内核根据注册insmod的驱动设备,找到相应的设备号(即相应的设备文件);
- 内核根据设备号 调用文件的操作方式,在内核中是file_operations结构体中;
- 根据驱动重写的相关函数,如open,release,unlocked_ioctl等,内核调用相关驱动函数从而实现应用层的open, close, ioctl.
.
Note:
1. 幻数加密
use magic number to encrypt the args. In order to avoid call in accident. 使用幻数进行加密,防止应用层误操作.
2. 驱动添加到内核/从内核卸载
编译好的驱动模块.ko文件, 首先需要加载驱动模块内核.
insmod xxx.ko
这个操作,会调用到驱动的module_init();
指向的具体模块加载函数;卸载驱动模块
rmmod xxx
这个操作则会调用到驱动的module_exit();
对应的卸载驱动函数;创建相应的设备文件, 这样应用层就可以方便统一方法访问所有文件和硬件设备.例如
open("/dev/xxx" , O_RDWR)
创建设备节点:
mknod /dev/xxx
注意: 这里不能够直接创建设备文件:
touch /dev/xxx
, 而是创建设备节点.