内存幻象器 (RAM Disk Lite)

在内核分配一页内存,通过 read/write 操作这块内存

项目简介

内存幻象器(RAM Disk Lite)是一个简单的Linux内核驱动项目,它在内核空间分配一页内存(通常为4KB),并通过文件操作接口(如read和write)让用户空间程序能够访问和修改这块内存。本项目是理解内核内存管理和字符设备驱动的绝佳起点。

学习目标:掌握内核内存分配、字符设备驱动编写、文件操作接口实现,以及用户空间与内核空间的数据交换。

核心概念

实现步骤

  1. 分配一页内核内存(4KB)。
  2. 注册字符设备,并实现 file_operations 方法。
  3. 实现 read 方法:将内核内存中的数据复制到用户空间。
  4. 实现 write 方法:将用户空间的数据复制到内核内存。
  5. 创建设备文件,测试读写操作。

代码示例

初始化模块和内存分配

#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");

软件架构

用户空间 内核空间 硬件 read() write() 内存页 系统调用 数据拷贝 内存访问

关键函数说明

函数 描述
get_zeroed_page 分配一页内存并初始化为零。
register_chrdev 注册字符设备,获取主设备号。
copy_to_user 将数据从内核空间复制到用户空间。
copy_from_user 将数据从用户空间复制到内核空间。
unregister_chrdev 注销字符设备。
free_page 释放分配的内存页。

测试方法

  1. 编译并加载内核模块:insmod ramdisk_lite.ko
  2. 查看系统日志获取主设备号:dmesg | grep "RAM Disk Lite"
  3. 创建设备文件:mknod /dev/ramdisk c <major> 0
  4. 使用 echo 和 cat 测试读写:
    echo "Hello, RAM Disk!" > /dev/ramdisk
    cat /dev/ramdisk

注意:本示例代码仅用于教学目的,实际生产环境中需要更完善的错误处理和安全检查。