2025-03-18
每次打开字符设备驱动文件都会重新创建一个struct file
结构体。如果想为每个打开的文件保留私有的数据,可以使用file->private_data
成员。在驱动文件被关闭之前都可以访问该成员,当然也要在关闭文件之前释放分配的资源。
// simple.c
#include <linux/init.h>
#include <linux/io.h>
#include <linux/minmax.h>
#include <linux/module.h>
#include <linux/slab.h>
#define MAJOR_NUM 54
#define DEV_NAME "simpledev"
static int _open(struct inode *inode, struct file *file) {
pr_info("simple_open\n");
char *ptr = kzalloc(PAGE_SIZE, GFP_KERNEL);
if (!ptr)
return -ENOMEM;
memcpy(ptr, "1234567890\n", 11);
file->private_data = ptr;
pr_info("kzalloc 4096 bytes of memory\n");
return 0;
}
static ssize_t _read(struct file *file, char __user *user_buffer, size_t size,
loff_t *offs) {
pr_info("simple_read\n");
char *my_data = (char *)file->private_data;
if (!my_data)
return -1;
size = min(PAGE_SIZE, size);
int remain_len = copy_to_user(user_buffer, my_data, size);
return size - remain_len;
}
static ssize_t _write(struct file *file, const char __user *user_buffer,
size_t size, loff_t *offs) {
pr_info("simple_write\n");
char *my_data = (char *)file->private_data;
if (!my_data)
return -1;
size = min(PAGE_SIZE, size);
int remain_len = copy_from_user(my_data, user_buffer, size);
return size - remain_len;
}
static int _close(struct inode *inode, struct file *file) {
pr_info("simple_close\n");
if (file->private_data) {
kfree(file->private_data);
pr_info("kfree 4096 bytes of memory\n");
}
return 0;
}
static struct file_operations fops = {
.owner = THIS_MODULE,
.open = _open,
.read = _read,
.write = _write,
.release = _close,
};
static int __init simple_init(void) {
pr_info("simple_init\n");
int status = register_chrdev(MAJOR_NUM, DEV_NAME, &fops);
if (status < 0) {
pr_err("register_chrdev error\n");
return status;
}
return 0;
}
static void __exit simple_exit(void) {
pr_info("simple_exit\n");
unregister_chrdev(MAJOR_NUM, DEV_NAME);
}
module_init(simple_init);
module_exit(simple_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("heng30");
MODULE_VERSION("v0.0.1");
MODULE_DESCRIPTION("A simple kernel module");
#!/bin/sh
top-dir = $(shell pwd)
kernel-version = $(shell uname -r)
kernel-dir ?= /lib/modules/$(kernel-version)/build
obj-m += simple.o
all:
make -C $(kernel-dir) modules M=$(top-dir)
clean:
rm -f *.o *.ko *.mod *.mod.c *.order *.symvers *.dtbo
make -C $(kernel-dir) clean m=$(top-dir)
编译程序:make
安装驱动:insmod simple.ko
创建驱动文件:mknod /dev/simpledev c 54 0
读取数据:head -n 1 /dev/simpledev
写入数据:echo "hello" > /dev/simpledev
移除驱动:rmmod simple.ko
查看输出:dmesg
[24718.066010] simple_init
[24723.819010] simple_open
[24723.819016] kzalloc 4096 bytes of memory
[24723.819020] simple_read
[24723.819034] simple_close
[24723.819034] kfree 4096 bytes of memory
[24748.298867] simple_open
[24748.298875] kzalloc 4096 bytes of memory
[24748.298900] simple_write
[24748.298906] simple_close
[24748.298907] kfree 4096 bytes of memory
[24770.466970] simple_exit