#include<linux module.h="">
#include<linux fs.h="">
#include<linux cdev.h="">
#include<linux uaccess.h="">// copy_to_user
#include<linux device.h="">// class_create, device_create
#define DEVICE_NAME "hello_dev"
#define CLASS_NAME "hello_class"
staticdev_t dev_num; // 设备号
staticstructcdevmy_cdev;// cdev结构体
staticstructclass *my_class;// 类指针
staticstructdevice *my_device;// 设备指针
staticchar kernel_msg[] = "Hello from Kernel!";
// 打开设备
staticintmy_open(struct inode *inode, struct file *file) {
printk(KERN_INFO "Hello_Dev: Device opened");
return0;
}
// 读取数据
staticssize_tmy_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) {
int ret;
size_t len = sizeof(kernel_msg);
// 简单的逻辑:每次读取都返回完整字符串,不处理偏移量
if (count < len) return -EINVAL;
// 关键:使用copy_to_user
ret = copy_to_user(user_buf, kernel_msg, len);
if (ret != 0) {
return -EFAULT;
}
return len; // 返回实际读取的字节数
}
// 定义操作函数集
staticstructfile_operationsfops = {
.owner = THIS_MODULE,
.open = my_open,
.read = my_read,
};
// 模块初始化
staticint __init hello_init(void) {
int ret;
// 1. 动态分配设备号
ret = alloc_chrdev_region(&dev_num, 0, 1, DEVICE_NAME);
if (ret < 0) {
printk(KERN_ALERT "Hello_Dev: Failed to allocate major number");
return ret;
}
printk(KERN_INFO "Hello_Dev: Major = %d, Minor = %d", MAJOR(dev_num), MINOR(dev_num));
// 2. 初始化cdev并添加到内核
cdev_init(&my_cdev, &fops);
my_cdev.owner = THIS_MODULE;
ret = cdev_add(&my_cdev, dev_num, 1);
if (ret < 0) goto unregister_chrdev;
// 3. 自动创建设备节点 /dev/hello_dev
my_class = class_create(THIS_MODULE, CLASS_NAME);
if (IS_ERR(my_class)) {
ret = PTR_ERR(my_class);
goto delete_cdev;
}
my_device = device_create(my_class, NULL, dev_num, NULL, DEVICE_NAME);
if (IS_ERR(my_device)) {
ret = PTR_ERR(my_device);
goto destroy_class;
}
printk(KERN_INFO "Hello_Dev: Initialized successfully");
return0;
// 错误处理流程(倒序释放)
destroy_class:
class_destroy(my_class);
delete_cdev:
cdev_del(&my_cdev);
unregister_chrdev:
unregister_chrdev_region(dev_num, 1);
return ret;
}
// 模块卸载
staticvoid __exit hello_exit(void) {
device_destroy(my_class, dev_num);
class_destroy(my_class);
cdev_del(&my_cdev);
unregister_chrdev_region(dev_num, 1);
printk(KERN_INFO "Hello_Dev: Goodbye");
}
module_init(hello_init);
module_exit(hello_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Embedded Engineer");
MODULE_DESCRIPTION("A simple Hello World character driver");
</linux></linux></linux></linux></linux>