Linux设备驱动(LDD)
代码可以点击这里
Linux设备的几个要点:
- 工作在内核态
- 硬件设备作为文件看待
- 使用文件接口对设备进行控制
Linux设备的分类(一种划分方式):
- 字符设备
- 块设备
- 网络设备
1. 了解设备
在Linux的/dev/
目录(device缩写)下有我们的设备文件
以c开头的都是字符设备,b开头的都是块设备,后面依次有主、次设备号,主设备号用于标识设备种类(范围为1-255),次设备号用来标识不同的硬件设备,最后是相应的设备文件。
2. 设备驱动程序
功能完整的LDD结构(一般至少要包含1,2,3,4):
- 设备的打开
- 设备的释放
- 驱动程序的注册
- 驱动程序的注销
- 设备的读操作
- 设备的写操作
- 设备的控制操作
我们将设备当作文件看待,所以驱动程序就是使用文件操作接口对设备进行控制,文件操作结构体如下:
1 | struct file_operations { |
当然我们不一定都需要使用上述全部的文件操作接口,尝试用read
,write
,open
,release
等接口
这里详细说明一下read
接口,接口原型如下(write
接口是类似的):
1 | ssize_t (*read) (struct file * file, char __user * buf, size_t count, loff_t * ppos); |
返回值:读取的大小
参数说明(形参名可以不同哈):
file
:与字符设备文件关联的file结构,由内核创建buf
:从设备文件读取到的数据,需要保存到的位置。由read系统调用提供该参数count
:请求传输的数据量,由read系统调用提供该参数ppos
:文件的读写位置,由内核从file结构中取出后,传递进来
直观理解可以看下面这张图
读取的过程其实就是将设备中file
中的内容读取到buf
中,其中ppos
表示file
中的偏移量(单位是字节),而count
表示需要读出的字节数。
读取可以使用copy_to_user()
函数(将内核空间的数据拷贝到用户空间,相应的写入数据可以使用copy_from_user()
函数)
3. 字符设备驱动程序开发(读取int数据)
3.1 驱动程序
定义了一个能够保存128个int数据的缓冲区,然后使用read
和write
完成整型数据的读取,代码如下,注释应该还是比较详细 :-)
1 |
|
3.2 安装配置驱动
然后编译即可,Makefile如下:
1 | obj-m += intDevice.o |
然后安装驱动模块:
1 | sudo insmod intDevice.ko |
然后可以使用如下命令查看
1 | cat /proc/devices |
然后创建设备文件
1 | mknod /dev/[设备名] c [主设备号] [次设备号] |
然后就能看到我们创建的设备文件
1 | ls -l /dev/ |
3.3 测试驱动
使用如下的测试代码对驱动程序进行简单测试
1 |
|
运行测试程序,似乎是没什么问题哈 :-)
(注意要用root权限,否则可能打开不了设备)