/*
\*file char_dev.c
\*brief the source for homework2.3
\* homework2.3: linux kernel code
\*author huangzhifu<huangzhifu@tp-link.com.hk>
\*version 1.0.0
\*date 08/07/2025
\*history
*/
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/device.h>
#include <linux/cdev.h>
#include <linux/slab.h>
#include <linux/ctype.h>
#define DEVICE_NAME "my_char_dev"
#define CLASS_NAME "my_char_class"
// 在模块代码中添加模块信息宏
MODULE_INFO(intree, "N"); // 明确声明为out-of-tree模块
MODULE_VERSION("1.0");
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Your Name");
MODULE_DESCRIPTION("Character device driver with uppercase option");
static int cap = 0;
module_param(cap, int, S_IRUGO);
MODULE_PARM_DESC(cap, "Enable uppercase conversion (1=enable)");
static int major_num;
static struct class *char_class = NULL;
static struct cdev my_cdev;
static ssize_t dev_write(struct file *filp, const char __user *buf,
size_t count, loff_t *f_pos)
{
char *kernel_buf;
int i;
// 分配内核缓冲区(+1用于空字符)
kernel_buf = kmalloc(count + 1, GFP_KERNEL);
if (!kernel_buf)
return -ENOMEM;
// 从用户空间复制数据
if (copy_from_user(kernel_buf, buf, count)) {
kfree(kernel_buf);
return -EFAULT;
}
kernel_buf[count] = '\0'; // 确保字符串终止
// 大写转换处理
if (cap) {
for (i = 0; i < count; i++)
kernel_buf[i] = toupper(kernel_buf[i]);
}
// 打印内核日志(实际使用时建议用print_hex_dump)
printk(KERN_INFO "Received %zu bytes: %s\n", count, kernel_buf);
kfree(kernel_buf);
return count;
}
static struct file_operations fops = {
.owner = THIS_MODULE,
.write = dev_write,
};
static int __init char_dev_init(void)
{
dev_t dev_num;
// 动态分配设备号
if (alloc_chrdev_region(&dev_num, 0, 1, DEVICE_NAME) < 0)
return -1;
major_num = MAJOR(dev_num);
// 初始化cdev结构
cdev_init(&my_cdev, &fops);
my_cdev.owner = THIS_MODULE;
// 添加字符设备到系统
if (cdev_add(&my_cdev, dev_num, 1) < 0) {
unregister_chrdev_region(dev_num, 1);
return -1;
}
// 创建设备类
char_class = class_create(THIS_MODULE, CLASS_NAME);
if (IS_ERR(char_class)) {
cdev_del(&my_cdev);
unregister_chrdev_region(dev_num, 1);
return PTR_ERR(char_class);
}
// 创建设备节点
device_create(char_class, NULL, dev_num, NULL, DEVICE_NAME);
printk(KERN_INFO "Char device loaded (cap=%d)\n", cap);
return 0;
}
static void __exit char_dev_exit(void)
{
dev_t dev_num = MKDEV(major_num, 0);
// 销毁设备节点和类
device_destroy(char_class, dev_num);
class_destroy(char_class);
// 删除cdev并释放设备号
cdev_del(&my_cdev);
unregister_chrdev_region(dev_num, 1);
printk(KERN_INFO "Char device unloaded\n");
}
module_init(char_dev_init);
module_exit(char_dev_exit);
详细解释每一行代码,包括每一行中的参量含义,需要详细具体