最简单的字符型设备驱动,仅支持读写和文件创建
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#define DEVICE_NAME "mem_device"
#define MEM_SIZE 4096
static dev_t dev;
static struct cdev c_dev;
static struct class *cl;
static char *device_memory;
static int major = 0;
static int minor = 0;
static int mem_device_open(struct inode *inode, struct file *file)
{
return 0;
}
static int mem_device_release(struct inode *inode, struct file *file)
{
return 0;
}
static ssize_t mem_device_read(struct file *file, char __user *buf, size_t count, loff_t *pos)
{
int bytes_to_read = count;
if (bytes_to_read > (MEM_SIZE - *pos)) {
bytes_to_read = (MEM_SIZE - *pos);
}
if (copy_to_user(buf, &device_memory[*pos], bytes_to_read) != 0) {
return -EFAULT;
}
*pos += bytes_to_read;
return bytes_to_read;
}
static ssize_t mem_device_write(struct file *file, const char __user *buf, size_t count, loff_t *pos)
{
int bytes_to_write = count;
if (bytes_to_write > (MEM_SIZE - *pos)) {
bytes_to_write = (MEM_SIZE - *pos);
}
if (copy_from_user(&device_memory[*pos], buf, bytes_to_write) != 0) {
return -EFAULT;
}
*pos += bytes_to_write;
return bytes_to_write;
}
static const struct file_operations mem_device_fops = {
.owner = THIS_MODULE,
.open = mem_device_open,
.release = mem_device_release,
.read = mem_device_read,
.write = mem_device_write,
};
static int __init mem_driver_init(void)
{
if (major != 0) {
dev = MKDEV(major, minor);
if (register_chrdev_region(dev, 1, DEVICE_NAME) < 0) {
if (alloc_chrdev_region(&dev, 0, 1, DEVICE_NAME) < 0) {
return -1;
}
}
} else {
if (alloc_chrdev_region(&dev, 0, 1, DEVICE_NAME) < 0) {
return -1;
}
major = MAJOR(dev);
minor = MINOR(dev);
}
if ((cl = class_create(THIS_MODULE, DEVICE_NAME)) == NULL) {
unregister_chrdev_region(dev, 1);
return -1;
}
if (device_create(cl, NULL, dev, NULL, DEVICE_NAME) == NULL) {
class_destroy(cl);
unregister_chrdev_region(dev, 1);
return -1;
}
cdev_init(&c_dev, &mem_device_fops);
if (cdev_add(&c_dev, dev, 1) == -1) {
device_destroy(cl, dev);
class_destroy(cl);
unregister_chrdev_region(dev, 1);
return -1;
}
device_memory = kmalloc(MEM_SIZE, GFP_KERNEL);
if (!device_memory) {
cdev_del(&c_dev);
device_destroy(cl, dev);
class_destroy(cl);
unregister_chrdev_region(dev, 1);
return -1;
}
printk(KERN_INFO "Memory device driver loaded\n");
return 0;
}
static void __exit mem_driver_exit(void)
{
kfree(device_memory);
cdev_del(&c_dev);
device_destroy(cl, dev);
class_destroy(cl);
unregister_chrdev_region(dev, 1);
printk(KERN_INFO "Memory device driver unloaded\n");
}
module_param(major, int, 0644);
MODULE_PARM_DESC(major, "Major number");
module_param(minor, int, 0644);
MODULE_PARM_DESC(minor, "Minor number");
module_init(mem_driver_init);
module_exit(mem_driver_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Maxwell");
MODULE_DESCRIPTION("A simple character device driver for memory access");