Linux字符设备驱动示例
下面是一个简化的Linux字符设备驱动示例,用于说明字符设备驱动的基本结构和操作流程,体现字符设备驱动的开发框架。在实际开发中,您需要根据具体硬件和需求来完善驱动程序。
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/device.h>
#define DEVICE_NAME "mychardev"
#define DEVICE_COUNT 1
static dev_t first_device_number; // 全局变量,设备号
static struct cdev my_cdev; // cdev结构体
// 设备打开函数
static int my_open(struct inode *inode, struct file *file) {
printk(KERN_INFO "Device opened\n");
return 0;
}
// 设备读取函数
static ssize_t my_read(struct file *file, char __user *buffer, size_t length, loff_t *offset) {
// 实现读取逻辑
return 0; // 返回实际读取的字节数
}
// 设备写入函数
static ssize_t my_write(struct file *file, const char __user *buffer, size_t length, loff_t *offset) {
// 实现写入逻辑
char buf[20];
memset( buf, 0, sizeof(buf) );
copy_from_user( buf, buffer, length );
printk(KERN_INFO "app write = %s\n", buf );
return length; // 返回实际写入的字节数
}
// 设备关闭函数
static int my_release(struct inode *inode, struct file *file) {
printk(KERN_INFO "Device closed\n");
return 0;
}
// 定义文件操作结构体
static const struct file_operations my_fops = {
.owner = THIS_MODULE,
.read = my_read,
.write = my_write,
.open = my_open,
.release = my_release,
// 其他操作...
};
// 初始化函数
static int __init my_chardev_init(void) {
int ret;
// 动态分配主设备号
ret = alloc_chrdev_region(&first_device_number, 0, DEVICE_COUNT, DEVICE_NAME);
if (ret < 0) {
printk(KERN_ERR "Failed to allocate char device region\n");
return ret;
}
// 初始化cdev结构体
cdev_init(&my_cdev, &my_fops);
my_cdev.owner = THIS_MODULE;
// 添加cdev到系统
ret = cdev_add(&my_cdev, first_device_number, DEVICE_COUNT);
if (ret < 0) {
printk(KERN_ERR "Failed to add char device\n");
unregister_chrdev_region(first_device_number, DEVICE_COUNT);
return ret;
}
printk(KERN_INFO "major =%d, minor =%d\n", \
MAJOR(first_device_number), MINOR(first_device_number));
return 0;
}
// 退出函数
static void __exit my_chardev_exit(void) {
// 删除cdev
cdev_del(&my_cdev);
// 释放设备号
unregister_chrdev_region(first_device_number, DEVICE_COUNT);
printk(KERN_INFO "Char device unregistered\n");
}
module_init(my_chardev_init);
module_exit(my_chardev_exit);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Simple Character Device Driver");
在这个示例中,我们定义了一个字符设备驱动程序,包括设备打开、读取、写入和关闭的基本操作。在my_chardev_init函数中,我们动态分配了设备号,并初始化了cdev结构体,然后将其添加到系统中。在my_chardev_exit函数中,我们删除了cdev并释放了设备号。
请注意,这个示例缺少了一些关键的实现,比如my_read和my_write函数的具体实现。在实际开发中,您需要根据您的硬件设备来实现这些函数,以执行实际的读取和写入操作。
此外,为了编译这个驱动程序,您需要编写一个Makefile,并使用适当的内核头文件和编译器选项来编译它。然后,您可以使用insmod命令加载模块,并使用rmmod命令卸载模块。在加载模块后,您可以使用mknod命令在/dev目录下创建一个设备节点,以便用户空间程序可以访问这个字符设备。
具体如何使用该驱动,以及代码测试流程请听下回分解。