#Linux杂记--Linux 内核态下的文件操作

#Linux杂记--Linux 内核态下的文件操作

引言

       总所周知,用户态进程读写任何类型的文件系统都可以使用read和write着两个系统调用,但是在linux内核中没有这样的系统调用我们如何操作文件呢?我们知道read和write在进入内核态之后,实际执行的是sys_read和sys_write,但是查看内核源代码,发现这些操作文件的函数都没有导出(使用EXPORT_SYMBOL导出),也就是说在内核模块中是不能使用的。
       接下来将在本文实现 Linux 内核态的文件读写操作,网上的很多教程都是过时的,尤其是对于 Linux 内核版本在 4.14 之后,已经不再支持 vfs_read 和 vfs_write 函数了,但网上大多数文章和示例都仍在使用,却并未做出任何说明。


相关函数介绍

/**
 * 在内核中打开的文件时需要注意打开的时机,
 * 很容易出现需要打开文件的驱动很早就加载并打开文件,但需要打开的文件所在设备还不有挂载到文件系统中,而导致打开失败。
 * 
 * @param filename  表明要打开或创建文件的名称(包括路径部分)。
 * @param mode      文件的打开方式,其取值与标准库中的open相应参数类似,可以取O_CREAT,O_RDWR,O_RDONLY等。
 * @param flags     创建文件时使用,设置创建文件的读写权限,其它情况可以匆略设为0
 * @return          返回strcut file*结构指针,供后继函数操作使用
 */
strcut file* filp_open(const char* filename, int mode, int flags);

/**
 * 关闭文件
 *
 * @param filp  strcut file*结构指针
 * @param id    传 NULL 即可
 */
int filp_close(struct file*filp, fl_owner_t id);

/**
 *
 * @param filp      strcut file*结构指针
 * @param buffer    指向用户空间的缓冲区
 * @param len       数据长度
 * @param pos       读写起始位置
 * @return          读取字节数
 */
ssize_t vfs_read(struct file* filp, char __user* buffer, size_t len, loff_t* pos);

/**
 *
 * @param filp      strcut file*结构指针
 * @param buffer    指向用户空间的缓冲区
 * @param len       数据长度
 * @param pos       读写起始位置
 * @return          写入字节数
 */
ssize_t vfs_write(struct file* filp, const char __user* buffer, size_t len, loff_t* pos);

// Linux 4.14 及其之后的版本使用,参数含义同 vfs_read
ssize_t kernel_read(struct file *file, void *buf, size_t count, loff_t *pos);

// Linux 4.14 及其之后的版本使用,参数含义同 vfs_write
ssize_t kernel_write(struct file *file, const void *buf, size_t count, loff_t *pos);

实现代码

       相关头文件

#include <linux/fs.h>
#include <linux/buffer_head.h>
#include <asm/segment.h>
#include <asm/uaccess.h>

       打开文件

struct file *file_open(const char *path, int mode, int flags) 
{
    struct file *filp = NULL;
    mm_segment_t oldfs;
    int err = 0;

    oldfs = get_fs();
    set_fs(get_ds());
    filp = filp_open(path, mode, flags);
    set_fs(oldfs);
    if (IS_ERR(filp)) {
        err = PTR_ERR(filp);
        return NULL;
    }
    return filp;
}

       关闭文件

void file_close(struct file *file) 
{
    filp_close(file, NULL);
}

       读取文件,Linux 内核版本4.14及其之后

int file_read(struct file *file, unsigned long long offset, unsigned char *data, unsigned int size) 
{
    mm_segment_t oldfs;
    int ret;

    oldfs = get_fs();
    set_fs(get_ds());

    ret = kernel_read(file, data, size, &offset);

    set_fs(oldfs);
    return ret;
}   

       写入文件,Linux 内核版本4.14及其之后

int file_write(struct file *file, unsigned long long offset, unsigned char *data, unsigned int size) 
{
    mm_segment_t oldfs;
    int ret;

    oldfs = get_fs();
    set_fs(get_ds());

    ret = kernel_write(file, data, size, &offset);

    set_fs(oldfs);
    return ret;
}

       读取文件,Linux 内核版本4.14之前

int file_read(struct file *file, unsigned long long offset, unsigned char *data, unsigned int size) 
{
    mm_segment_t oldfs;
    int ret;

    oldfs = get_fs();
    set_fs(get_ds());

    ret = vfs_read(file, data, size, &offset);

    set_fs(oldfs);
    return ret;
}   

       写入文件,Linux 内核版本4.14之前

int file_write(struct file *file, unsigned long long offset, unsigned char *data, unsigned int size) 
{
    mm_segment_t oldfs;
    int ret;

    oldfs = get_fs();
    set_fs(get_ds());

    ret = vfs_write(file, data, size, &offset);

    set_fs(oldfs);
    return ret;
}
  • 3
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值