以下是一个简单的Linux字符设备驱动开发示例:
一、基础概念
/dev
目录下。二、示例代码(简单的字符设备驱动)
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#define DEVICE_NAME "my_char_device"
#define CLASS_NAME "my_char_class"
static int major_number;
static struct class* my_class = NULL;
static struct device* my_device = NULL;
// 设备操作函数
static ssize_t device_read(struct file* filp, char* buffer, size_t length, loff_t* offset)
{
printk(KERN_INFO "Read function called
");
// 简单返回一个固定字符串
const char* msg = "Hello from my char device";
int len = strlen(msg);
if (*offset >= len)
return 0;
if (*offset + length > len)
length = len - *offset;
if (copy_to_user(buffer, msg + *offset, length))
return -EFAULT;
*offset += length;
return length;
}
static ssize_t device_write(struct file* filp, const char* buffer, size_t length, loff_t* offset)
{
printk(KERN_INFO "Write function called
");
// 这里简单打印写入的数据长度
printk(KERN_INFO "Written data length: %zu
", length);
return length;
}
static struct file_operations fops = {
.read = device_read,
.write = device_write,
};
// 模块初始化函数
static int __init my_driver_init(void)
{
major_number = register_chrdev(0, DEVICE_NAME, &fops);
if (major_number < 0) {
printk(KERN_ALERT "Failed to register device, error code: %d
", major_number);
return major_number;
}
printk(KERN_INFO "Registered correctly with major number %d
", major_number);
my_class = class_create(THIS_MODULE, CLASS_NAME);
if (IS_ERR(my_class)) {
unregister_chrdev(major_number, DEVICE_NAME);
printk(KERN_ALERT "Failed to create class
");
return PTR_ERR(my_class);
}
printk(KERN_INFO "Class created successfully
");
my_device = device_create(my_class, NULL, MKDEV(major_number, 0), NULL, DEVICE_NAME);
if (IS_ERR(my_device)) {
class_destroy(my_class);
unregister_chrdev(major_number, DEVICE_NAME);
printk(KERN_ALERT "Failed to create device
");
return PTR_ERR(my_device);
}
printk(KERN_INFO "Device created successfully
");
return 0;
}
// 模块退出函数
static void __exit my_driver_exit(void)
{
device_destroy(my_class, MKDEV(major_number, 0));
class_unregister(my_class);
class_destroy(my_class);
unregister_chrdev(major_number, DEVICE_NAME);
printk(KERN_INFO "Goodbye, driver!
");
}
module_init(my_driver_init);
module_exit(my_driver_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Your Name");
MODULE_DESCRIPTION("A simple Linux character device driver example");
三、优势
四、类型
五、应用场景
六、常见问题及解决方法
register_chrdev
函数的返回值,确保设备名称、操作函数指针等参数正确。class_create
和device_create
函数的执行情况,查看内核日志(dmesg
命令)获取更多信息。read
和write
函数中,检查指针操作是否正确,特别是copy_to_user
和copy_from_user
函数的使用,确保不会发生内存访问越界等问题。请注意,这只是一个非常基础的示例,在实际的驱动开发中,还需要考虑更多的因素,如中断处理、设备初始化和配置等。
高校公开课
企业创新在线学堂
T-Day
腾讯云数据库TDSQL训练营
腾讯云数据库TDSQL训练营
腾讯云数据库TDSQL训练营
腾讯云数据库TDSQL训练营
腾讯云数据库TDSQL训练营
腾讯云数据库TDSQL训练营
腾讯云数据库TDSQL训练营
腾讯云数据库TDSQL训练营
腾讯云数据库TDSQL(PostgreSQL版)训练营
领取专属 10元无门槛券
手把手带您无忧上云