项目简介
内存幻象器(RAM Disk Lite)是一个简单的Linux内核驱动项目,它在内核空间分配一页内存(通常为4KB),并通过文件操作接口(如read和write)让用户空间程序能够访问和修改这块内存。本项目是理解内核内存管理和字符设备驱动的绝佳起点。
学习目标:掌握内核内存分配、字符设备驱动编写、文件操作接口实现,以及用户空间与内核空间的数据交换。
核心概念
- 内核内存分配:使用
kmalloc
或get_free_page
分配内存。 - 字符设备驱动:实现
file_operations
结构体中的 read、write 等方法。 - 设备文件:通过
/dev/
目录下的文件与驱动交互。 - 用户空间与内核空间:通过 copy_to_user 和 copy_from_user 交换数据。
实现步骤
- 分配一页内核内存(4KB)。
- 注册字符设备,并实现 file_operations 方法。
- 实现 read 方法:将内核内存中的数据复制到用户空间。
- 实现 write 方法:将用户空间的数据复制到内核内存。
- 创建设备文件,测试读写操作。
代码示例
初始化模块和内存分配
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/slab.h>
#define DEVICE_NAME "ramdisk_lite"
#define PAGE_SIZE 4096
static char *ramdisk_buffer;
static int major_number;
static int device_open(struct inode *inode, struct file *file) {
return 0;
}
static int device_release(struct inode *inode, struct file *file) {
return 0;
}
static ssize_t device_read(struct file *filp, char __user *buffer, size_t length, loff_t *offset) {
if (*offset >= PAGE_SIZE) return 0;
if (*offset + length > PAGE_SIZE) length = PAGE_SIZE - *offset;
if (copy_to_user(buffer, ramdisk_buffer + *offset, length)) return -EFAULT;
*offset += length;
return length;
}
static ssize_t device_write(struct file *filp, const char __user *buffer, size_t length, loff_t *offset) {
if (*offset >= PAGE_SIZE) return 0;
if (*offset + length > PAGE_SIZE) length = PAGE_SIZE - *offset;
if (copy_from_user(ramdisk_buffer + *offset, buffer, length)) return -EFAULT;
*offset += length;
return length;
}
static struct file_operations fops = {
.open = device_open,
.release = device_release,
.read = device_read,
.write = device_write,
};
static int __init ramdisk_init(void) {
ramdisk_buffer = (char *)get_zeroed_page(GFP_KERNEL);
if (!ramdisk_buffer) return -ENOMEM;
major_number = register_chrdev(0, DEVICE_NAME, &fops);
if (major_number < 0) {
free_page((unsigned long)ramdisk_buffer);
return major_number;
}
printk(KERN_INFO "RAM Disk Lite: major number %d\n", major_number);
return 0;
}
static void __exit ramdisk_exit(void) {
unregister_chrdev(major_number, DEVICE_NAME);
free_page((unsigned long)ramdisk_buffer);
printk(KERN_INFO "RAM Disk Lite: module unloaded\n");
}
module_init(ramdisk_init);
module_exit(ramdisk_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Your Name");
MODULE_DESCRIPTION("A simple RAM disk driver");
软件架构
关键函数说明
函数 | 描述 |
---|---|
get_zeroed_page | 分配一页内存并初始化为零。 |
register_chrdev | 注册字符设备,获取主设备号。 |
copy_to_user | 将数据从内核空间复制到用户空间。 |
copy_from_user | 将数据从用户空间复制到内核空间。 |
unregister_chrdev | 注销字符设备。 |
free_page | 释放分配的内存页。 |
测试方法
- 编译并加载内核模块:
insmod ramdisk_lite.ko
- 查看系统日志获取主设备号:
dmesg | grep "RAM Disk Lite"
- 创建设备文件:
mknod /dev/ramdisk c <major> 0
- 使用 echo 和 cat 测试读写:
echo "Hello, RAM Disk!" > /dev/ramdisk cat /dev/ramdisk
注意:本示例代码仅用于教学目的,实际生产环境中需要更完善的错误处理和安全检查。