提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
- 前言
- 一、内核文件操作接口?
- 二、代码示例
- 总结
前言
提示:这里可以添加本文要记录的大概内容:
linux内核中操作文件代码示例
内核版本:5.10
提示:以下是本篇文章正文内容,下面案例可供参考
一、内核文件操作接口?
struct file *filp_open(const char *filename, int flags, umode_t mode)
int filp_close(struct file *filp, fl_owner_t id)
//ssize_t vfs_read(struct file *file, char __user *buf, size_t count, loff_t *pos)
//ssize_t vfs_write(struct file *file, const char __user *buf, size_t count, loff_t *pos)
ssize_t kernel_read(struct file *file, void *buf, size_t count, loff_t *pos)
ssize_t kernel_write(struct file *file, const void *buf, size_t count,
loff_t *pos)
//以下函数内核没有导出
删除文件:
long do_unlinkat(int dfd, struct filename *name)
do_unlinkat(AT_FDCWD, getname_kernel(“/root/test”));
删除文件夹:
long do_rmdir(int dfd, struct filename *name)
do_rmdir(AT_FDCWD, getname(pathname)); // getname需要用户层地址,内核使用getname_kernel
二、代码示例
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/sysfs.h>#include <linux/fs.h>
#include <linux/namei.h>
#include <linux/slab.h>
#include <linux/mm.h>
#include <linux/binfmts.h>
#include <linux/kallsyms.h>#define DEVICE_NAME "mychardev"
#define CLASS_NAME "mychardev_class"static dev_t dev_num; // 设备号
static struct cdev my_cdev; // cdev 结构体
static struct class *my_class; // 设备类
static struct device * my_device;#define BUFFER_SIZE 1024 // 定义缓冲区大小ssize_t open_read_close_file(const char *path)
{struct file *filp;char *buffer;ssize_t bytes_read;int err;// 分配缓冲区以存储读取的数据buffer = kmalloc(BUFFER_SIZE, GFP_KERNEL);if (!buffer) {return -ENOMEM; // 内存分配失败}// 使用 filp_open 打开文件filp = filp_open(path, O_RDWR | O_CREAT, 0644);if (IS_ERR(filp)) {kfree(buffer); // 释放缓冲区return -1;}// 从文件读取数据bytes_read = kernel_read(filp, buffer, BUFFER_SIZE - 1, &filp->f_pos);if (bytes_read >= 0) {buffer[bytes_read] = '\0'; // 确保字符串结束符printk(KERN_INFO "Read from file: %s\n", buffer); // 打印读取的内容} else {printk(KERN_ERR "Failed to read from file: %ld\n", bytes_read);}// 关闭文件filp_close(filp, NULL);return bytes_read; // 返回读取的字节数}// 设备打开操作
static int my_open(struct inode *inode, struct file *file)
{// 在这里执行打开设备的操作return 0;
}// 设备关闭操作
static int my_release(struct inode *inode, struct file *file)
{// 在这里执行关闭设备的操作return 0;
}// 设备读取操作
static ssize_t my_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
{// 在这里执行读取数据的操作return count;
}// 设备写入操作
static ssize_t my_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
{// 在这里执行写入数据的操作char command[256];int cmd = 0;int ret = 0;if (count > sizeof(command) - 1) {return -EINVAL;}ret = copy_from_user(command, buf, count);if (ret) {return -EFAULT;}// 终止字符串command[count] = '\0';sscanf(command, "%d", &cmd);printk("cmd = %d\n", cmd);switch(cmd){case 1:open_read_close_file("./test_file");break;case 2:break;case 3:break;default:break;}return count;
}// 设备 ioctl 操作
static long my_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{// 在这里执行 ioctl 操作return 0;
}// 设备操作函数表
static const struct file_operations fops = {.owner = THIS_MODULE,.open = my_open,.release = my_release,.read = my_read,.write = my_write,.unlocked_ioctl = my_ioctl,
};static ssize_t show_my_sysfs_node(struct device *dev, struct device_attribute *attr, char *buf)
{/* 这里实现读取 sysfs 文件的内容 */return sprintf(buf, "Hello from the kernel!\n");
}static ssize_t store_my_sysfs_node(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{/* 这里实现写入 sysfs 文件的行为 */pr_info("Received '%.*s'\n", (int)count, buf);return count;
}static DEVICE_ATTR(my_sysfs_node, 0644, show_my_sysfs_node, store_my_sysfs_node);// 模块加载时的初始化函数
static int __init my_init(void)
{int result;// 动态分配设备号result = alloc_chrdev_region(&dev_num, 0, 1, DEVICE_NAME);if (result < 0) {printk(KERN_ERR "Failed to allocate character device region.\n");return result;}// 初始化 cdev 结构体cdev_init(&my_cdev, &fops);// 注册 cdevresult = cdev_add(&my_cdev, dev_num, 1);if (result) {unregister_chrdev_region(dev_num, 1);printk(KERN_ERR "Failed to add cdev.\n");return result;}// 创建设备类my_class = class_create(THIS_MODULE, CLASS_NAME);if (IS_ERR(my_class)) {cdev_del(&my_cdev);unregister_chrdev_region(dev_num, 1);printk(KERN_ERR "Failed to create device class.\n");return PTR_ERR(my_class);}// 创建设备节点my_device = device_create(my_class, NULL, dev_num, NULL, DEVICE_NAME);printk(KERN_INFO "Character device '%s' created with major number %d.\n", DEVICE_NAME, MAJOR(dev_num));// 创建 sysfs 文件节点device_create_file(my_device, &dev_attr_my_sysfs_node);return 0;
}// 模块卸载时的清理函数
static void __exit my_exit(void)
{// 删除 sysfs 文件节点device_remove_file(my_device, &dev_attr_my_sysfs_node);// 删除设备节点device_destroy(my_class, dev_num);// 删除设备类class_destroy(my_class);// 删除 cdevcdev_del(&my_cdev);// 释放设备号unregister_chrdev_region(dev_num, 1);printk(KERN_INFO "Character device '%s' removed.\n", DEVICE_NAME);
}module_init(my_init);
module_exit(my_exit);MODULE_LICENSE("GPL");
MODULE_AUTHOR("Your Name");
MODULE_DESCRIPTION("A simple character device driver.");
Makefile
obj-m += module_char_test.oall:make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modulesclean:make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
总结
linux内核中操作文件代码示例,可以运行,内核接口可以在内核源码 fs/ 目录下的文件(不用看目录)查找,open相关操作在fs/open.c ,read write在fs/read_write.c,可以找下试下。
参考链接:
https://blog.csdn.net/w968516q/article/details/77964853