内核空间文件操作函数注释


内核空间读写文件的常规操作步骤同用户空间一样

第一步:打开文件,获取文件指针

第二步:将文件读入到一段内存中

第三步:将一段内存中的数据写入到另一个文件中。

完成上述功能要用的内核函数有:

◆打开文件filp_open()

◆关闭文件filp_close()

◆读文件内容到内存中vfs_read()

◆写内存中的数据到文件vfs_write()

函数 filp_open(const char* filename, int open_mode, int mode)

函数功能:在内核空间中打开文件

函数原形:

strcut file* filp_open(const char* filename, int open_mode, int mode);

返回值:strcut file*结构指针,供后继函数操作使用,该返回值用IS_ERR()来检验其有效性。

参数:

filename:表明要打开或创建文件的名称(包括路径部分)。

open_mode:文件的打开方式,O_RDONLY 只读打开、O_WRONLY 只写打开、O_RDWR 读写打开、O_CREAT 文件不存在则创建。

mode:创建文件时使用,设置创建文件的权限,其它情况可以匆略设为0

示例

struct file *file = NULL;

file = filp_open(/root/test.txt,O_RDWR|O_CREAT,0);

//以读写方式(没有则创建)打开文件/root/test.txt。并返回test.txt的文件指针给file.
函数 filp_close(struct file*filp, fl_owner_t id)

函数功能:关闭之前打开文件

函数原型:int filp_close(struct file*filp, fl_owner_t id);

参数:

struct file*filp:打开文件的文件指针

fl_owner_t id:一般传递NULL值,也可用current->files作为实参。

示例

filp_close(file, NULL); //关闭指针为file的文件。
函数 vfs_read(struct file *file, char __user *buf, size_t count, loff_t *pos)

函数功能:读取已经打开的文件到内存中

函数原型:

ssize_t vfs_read(struct file *file, char __user *buf, size_t count, loff_t *pos)

{

    ssize_t ret;

    if (!(file->f_mode & FMODE_READ)) //判断文件是否可读

        return -EBADF;

    if (!file->f_op || (!file->f_op->read && !file->f_op->aio_read)) //是否定义文件读方法

        return -EINVAL;

    if (unlikely(!access_ok(VERIFY_WRITE, buf, count))) 

        return -EFAULT;

    ret = rw_verify_area(READ, file, pos, count); //读校验 ,

    if (ret >= 0) 

      {

          count = ret;

          if (file->f_op->read) 

          ret = file->f_op->read(file, buf, count, pos); //调用文件读操作方法

          else

          ret = do_sync_read(file, buf, count, pos); //通用文件模型读方法

          if (ret > 0)

            {

                 fsnotify_access(file->f_path.dentry);

                 add_rchar(current, ret);

             }

          inc_syscr(current);

      }

    return ret;

}

通过filp_open我们已经可以在当前进程的文件描述表中找到了file , 于是我们就可以调用保存在file中的文件操作方法(file_operation) file->f_op->read(file, buf, count, pos)来具体的操作文件。

上面的代码实现并不复杂,在做了一些条件判断以后,如果该文件索引节点inode定义了文件的读实现方法的话,就调用此方法。Linux下特殊文件读往往是用此方法, 一些伪文件系统如:proc,sysfs等,读写文件也是用此方法。而如果没有定义此方法就会调用通用文件模型的读写方法.它最终就是读内存,或者需要从存储介质中去读数据.

参数:

struct file *file:打开的文件返回的文件指针,(读的目标文件)

char __user *buf:在用户空间开辟的一段内存空间的首地址,用来保存文件数据。

size_t count:指定读取文件中的多少内容。单位字节

loff_t *pos:文件起始位置偏移值,若从文件头读取,则偏移值为0.可以在文件自身的信息中获取

示例

int *buf;

loff_t *pos = &(file->f_pos);

buf = (int *)kmalloc(fsize+100,GFP_KERNEL);

//分配一个文件自身大小+100字节边界的内存空间,将用来存放打开的文件,内存分配方式为kmalloc的flag标志GFP_KERNEL。

vfs_read(file, buf, fsize, pos); //读文件(指针为file)到内存(buf为起始地址)中,读取字节数定为文件自身大小,偏移为自身.
函数 vfs_write(struct file *file, const 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 ret;

    if (!(file->f_mode & FMODE_WRITE))

        return -EBADF;

    if (!file->f_op || (!file->f_op->write && !file->f_op->aio_write))

        return -EINVAL;

    if (unlikely(!access_ok(VERIFY_READ, buf, count)))

        return -EFAULT;

    ret = rw_verify_area(WRITE, file, pos, count);

    if (ret >= 0) 

      {

         count = ret;

         if (file->f_op->write)

         ret = file->f_op->write(file, buf, count, pos); 

         else

         ret = do_sync_write(file, buf, count, pos);

         if (ret > 0)

           {

                fsnotify_modify(file->f_path.dentry);

                add_wchar(current, ret);

            }

         inc_syscw(current);

      }

    return ret;

}

可以看出这个函数和vfs_read()是差不多的,只是调用的文件操作方法不同而已(file->f_op->write) ,如果没有定义file->f_op->write ,同样也需要do_sync_write()调用同样文件写操作, 首先把数据写到内存中,然后在适当的时候把数据同步到具体的存储介质中去.

参数:

struct file *file:打开的文件返回的文件指针,(写的目标文件)

char __user *buf:数据在内存中的位置,以该地址为起始的一段内存数据将要写到文件中

size_t count:指定写入文件中的多少内容。单位字节

loff_t *pos:文件起始位置偏移值,若从文件头读取,则偏移值为0.可以在文件自身的信息中获取

示例

loff_t *pos = &(file->f_pos);

vfs_write(file,buf,fsize,pos);
获取文件的大小

我们可以利用文件的inode结构获得文件的大小,参考代码如下

struct file *file = NULL;

struct inode *inode = NULL;

file = filp_open(file_path,O_RDWR|O_CREAT,0);

inode = file->f_dentry->d_inode;

fsize = inode->i_size;

printk(KERN_ALERT "size=%d/n",(int)fsize);
示例代码

此ko模块代码在arm架构的fpga上已经跑通。因为涉及的参数比较多,为了清楚地重现重要步骤,对每步骤的函数进行了简单的封装。参数的传递只要理解上面的介绍即可区分清楚。执行流程在static int hello_init(void)函数中

/*

* kernel_hello_file.c

*

* Created on: 2010-11-9

* Author: Wang BaoYi(zats)

* Email:wby0322@gmail.com

*/

#include <linux/kernel.h>

#include <linux/init.h>

#include <linux/module.h>

#include <linux/fs.h>

#include <linux/string.h>

#include <linux/mm.h>

#include <linux/syscalls.h>

#include <asm/unistd.h>

#include <asm/uaccess.h>

#define FILE_PATH_READ "/file_read_test"

//打开文件路径(包括文件名),未来将要读的

#define FILE_PATH_WRITE "/new_file_test"

//打开文件路径(包括文件名),未来将要写的

struct file *file = NULL; //保存打开文件的文件指针变量

struct inode *inode = NULL; //为了获取文件大小用的inode结构变量

int *file_buf; //保存开辟的内存空间的地址的指针变量

loff_t fsize; //保存文件大小的变量

mm_segment_t old_fs; //保存内存边界的变量

/*

* kernel_file_open封装了文件打开函数

* 参数为文件路径(包含文件名)。

* 操作file类型结构变量。

* 打开方式为读写(没有则创建)

*/

static int kernel_file_open(char *file_path)

{

    file = filp_open(file_path,O_RDWR|O_CREAT,0);

    if (IS_ERR(file)) 

      {

        printk("Open file %s failed./n", file_path);

        return 0;

      }

}

/*

* kernel_file_size封装了获取文件大小函数

* 参数为待获取大小的文件指针。

* 操作inode类型结构变量。

* 返回值为文件大小,单位字节

*/

static loff_t kernel_file_size(struct file *file)

{

    inode = file->f_dentry->d_inode;

    fsize = inode->i_size;

    printk(KERN_ALERT "size=%d/n",(int)fsize);

    return fsize;

}

/*

* kernel_addr_limit_expend封装了内存边界扩展函数

* 参数无。

*/

static int kernel_addr_limit_expend(void)

{

    old_fs = get_fs();

    set_fs(KERNEL_DS);
 
    return 0;

}

/*

* kernel_addr_limit_resume封装了内存边界恢复函数

* 参数无。

*/

static int kernel_addr_limit_resume(void)

{

    set_fs(old_fs);

}

/*

* kernel_file_read封装了读文件函数

* 参数为open的文件指针,获取的文件大小

* 返回值为读入到内存中的首地址。

*/

void *kernel_file_read(struct file *file,loff_t fsize)

{

    int *buf;

    loff_t *pos = &(file->f_pos);

    buf = (int *)kmalloc(fsize+100,GFP_KERNEL);

    vfs_read(file, buf, fsize, pos);

    return buf;

}

/*

* kernel_file_ write封装了读文件函数

* 参数为open的文件指针,数据在内存中的地址,写入到文件的字节数

*/

static int kernel_file_write(struct file *file,int *buf,loff_t fsize)

{

    loff_t *pos = &(file->f_pos);

    vfs_write(file,buf,fsize,pos);

}

/*

* ko的主函数

*/

static int hello_init(void) //ko的主函数

{

    printk(KERN_ALERT "Y(^_^)Y Hello Wang`s file./n");

    kernel_file_open(FILE_PATH_READ); //打开文件file_read_test

    kernel_file_size(file); //获取file_read_test的大小

    /*read file to mem*/

    kernel_addr_limit_expend(); //边界扩展

    file_buf = kernel_file_read(file,fsize); //读操作

    filp_close(file, NULL); //关闭文件file_read_test

    kernel_addr_limit_resume(); //边界恢复

    /*write mem to file*/

    kernel_file_open(FILE_PATH_WRITE); //打开文件new_file_test,没有则创建

    kernel_addr_limit_expend(); //边界扩展

    kernel_file_write(file,file_buf,fsize); //将前面读到内存中的数据,写入到文件new_file_test中

    filp_close(file, NULL); //关闭文件

    kernel_addr_limit_resume(); //边界恢复

    return 0;

}

static void hello_exit(void)

{

    printk(KERN_ALERT "BYE BYE file Y(^_^)Y/n");

}

module_init(hello_init);

module_exit(hello_exit);

MODULE_LICENSE("Dual BSD/GPL");

MODULE_AUTHOR("wby");

MODULE_DESCRIPTION("A simple hello world Module with File");
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Linux内核文件操作函数可以帮助我们在内核态对系统中的文件进行读取、写入、打开、关闭等许多操作。下面介绍几个常用的文件操作函数及其使用案例。 1. open()函数函数用于打开文件,可以根据需要进行读写和创建等不同的操作。其函数原型如下: ``` #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> int open(const char *pathname, int flags); int open(const char *pathname, int flags, mode_t mode); ``` flags参数用来指定打开文件时的模式,常用的模式包括: * O_RDONLY:只读模式 * O_WRONLY:只写模式 * O_RDWR:读写模式 * O_CREAT:文件不存在时创建文件 * O_APPEND:追加模式 mode参数用来指定创建文件时的权限,常用的权限包括: * S_IRUSR:用户具有读取权限 * S_IWUSR:用户具有写入权限 * S_IXUSR:用户具有执行权限 * S_IRGRP:组具有读取权限 * S_IWGRP:组具有写入权限 * S_IXGRP:组具有执行权限 * S_IROTH:其他用户具有读取权限 * S_IWOTH:其他用户具有写入权限 * S_IXOTH:其他用户具有执行权限 下面是一个使用open()函数打开并读取文件的例子: ``` #include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> int main(void) { int fd, n; char buf[1024]; fd = open("test.txt", O_RDONLY); if (fd < 0) { perror("open"); exit(EXIT_FAILURE); } n = read(fd, buf, 1024); if (n < 0) { perror("read"); exit(EXIT_FAILURE); } printf("The content of test.txt is:\n%s", buf); close(fd); return 0; } ``` 2. read()函数函数用于从文件中读取数据。其函数原型如下: ``` #include <unistd.h> ssize_t read(int fd, void *buf, size_t count); ``` fd参数是文件描述符,buf参数是读取数据的缓冲区,count参数是要读取的字节数。 下面是一个使用read()函数读取文件的例子: ``` #include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> int main(void) { int fd, n; char buf[1024]; fd = open("test.txt", O_RDONLY); if (fd < 0) { perror("open"); exit(EXIT_FAILURE); } n = read(fd, buf, 1024); if (n < 0) { perror("read"); exit(EXIT_FAILURE); } printf("The content of test.txt is:\n%s", buf); close(fd); return 0; } ``` 3. write()函数函数用于将数据写入文件中。其函数原型如下: ``` #include <unistd.h> ssize_t write(int fd, const void *buf, size_t count); ``` fd参数是文件描述符,buf参数是要写入的数据的缓冲区,count参数是要写入的字节数。 下面是一个使用write()函数写入文件的例子: ``` #include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> int main(void) { int fd, n; char buf[1024] = "This is a test for write() function.\n"; fd = open("test.txt", O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR); if (fd < 0) { perror("open"); exit(EXIT_FAILURE); } n = write(fd, buf, sizeof(buf)); if (n < 0) { perror("write"); exit(EXIT_FAILURE); } close(fd); return 0; } ``` 4. close()函数函数用于关闭文件。其函数原型如下: ``` #include <unistd.h> int close(int fd); ``` fd参数是文件描述符。 下面是一个使用close()函数关闭文件的例子: ``` #include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> int main(void) { int fd, n; char buf[1024]; fd = open("test.txt", O_RDONLY); if (fd < 0) { perror("open"); exit(EXIT_FAILURE); } /* do something */ close(fd); return 0; } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值