欢迎来到《QEMU-Friendly Linux内核驱动项目50例》的第二章!本章将带你创建一个有趣的字符设备驱动,它能够过滤用户写入的字符串,只将包含特定关键词的日志信息通过printk
打印到内核日志中。让我们一起探索这个神奇的内核世界吧!
本项目的目标是创建一个字符设备驱动,实现以下功能:
printk
打印到内核日志中。open
、release
、write
)。write
函数中,检查用户数据是否包含预设的关键词。printk
打印字符串到内核日志。#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#define DEVICE_NAME "log_filter"
#define KEYWORD "error"
static int major_num;
static char buffer[256];
static int buffer_size = 0;
static ssize_t device_write(struct file *filp, const char __user *buf, size_t len, loff_t *off) {
ssize_t retval = -ENOMEM;
if (len > sizeof(buffer) - 1) {
pr_err("Input too long\n");
return -EINVAL;
}
if (copy_from_user(buffer, buf, len)) {
return -EFAULT;
}
buffer[len] = '\0';
buffer_size = len;
if (strstr(buffer, KEYWORD) != NULL) {
printk(KERN_INFO "Filtered log: %s\n", buffer);
}
return len;
}
static struct file_operations fops = {
.owner = THIS_MODULE,
.write = device_write,
};
static int __init log_filter_init(void) {
major_num = register_chrdev(0, DEVICE_NAME, &fops);
if (major_num < 0) {
pr_err("Failed to register device: %d\n", major_num);
return major_num;
}
pr_info("Log filter device registered with major number %d\n", major_num);
return 0;
}
static void __exit log_filter_exit(void) {
unregister_chrdev(major_num, DEVICE_NAME);
pr_info("Log filter device unregistered\n");
}
module_init(log_filter_init);
module_exit(log_filter_exit);
编译并加载模块后,可以使用以下命令测试设备:
# 创建设备节点
mknod /dev/logfilter c 246 0
# 写入包含关键词的字符串
echo "This is an error message" > /dev/logfilter
# 写入不包含关键词的字符串
echo "This is a normal message" > /dev/logfilter
# 查看内核日志
dmesg | tail
输入内容 | 是否包含关键词 | 内核日志输出 |
---|---|---|
"System started normally" | 否 | 无输出 |
"Network error: connection failed" | 是 | "Filtered log: Network error: connection failed" |
"Warning: disk space low" | 否(除非关键词设置为"warning") | 无输出 |
copy_from_user
直接处理用户数据。