《原子嵌入式Linux驱动开发详解与实战》阅读体验2-字符设备
[复制链接]
驱动是连接底层硬件和上层应用的桥梁,通过文件系统IO访问设备文件,在用户层访问设备文件跟访问普通文件一样。
字符设备按照字节流进行读写操作,读写数据是分先后顺序。最常见LED灯、button、 IIC、 SPI,LCD 等等都是字符设备,这些设备的驱动就叫做字符设备驱动。
Linux 应用程序对驱动程序的调用流程如图所示:
Linux 中一切皆为文件,驱动加载成功以后会在“/dev”目录下生成一个相应的文件,应用程序通过对这个名为“/dev/xxx” (xxx 是具体的驱动文件名字)的文件进行相应的操作即可实现对硬件的操作。
字符设备驱动开发步骤如下:
1.确定设备号
可以使用静态分配设备号、以及使用动态分配设备号。
2.定义 file_operations 结构体
创建一个结构体,用于定义字符设备驱动程序对外提供的操作接口。常见的函数包括 'open'、'release'、'read'、'write'、'ioctl' 等。同时在驱动程序的初始化函数中,将这些操作函数与对应的函数指针关联起来。
3.实现操作函数
实现字符设备驱动中定义的操作函数,根据设备的需求来进行相应的操作。在 'open' 函数中可以进行设备的初始化工作,例如分配内存、初始化设备状态等。在 'release' 函数中可以进行设备的清理工作,例如释放内存、关闭设备等。在 'read' 函数中可以从设备读取数据,并将数据传递给用户空间。在 'write' 函数中可以接收用户空间传递的数据,并将数据写入设备。在 'ioctl' 函数中可以处理设备的特殊控制命令。
4.注册和注销字符设备
使用register_chrdev()和unregister_chrdev()函数进行设备注册和注销。
5.编译和加载模块
将驱动程序的源代码编译为内核模块,生成对应的 .ko 文件。使用modprobe加载模块到内核中。
6.用户空间交互
用户程序通过系统调用来访问字符设备,如使用 'open'、'read'、'write'、'ioctl' 等函数来打开、读取和写入设备。
最后来一段:
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/miscdevice.h>
// 文件操作接口
static const struct file_operations my_fops = {
.owner = THIS_MODULE,
// 其他需要实现的操作
};
// 注册字符设备
static int __init my_init(void) {
int ret;
ret = register_chrdev(200, "my_device", &my_fops);
if (ret < 0)
return ret;
return 0;
}
static void __exit my_exit(void) {
unregister_chrdev(200, "my_device");
}
module_init(my_init);
module_exit(my_exit);
MODULE_LICENSE("GPL");
|