linux内核态读写文件

        linux用户态通过文件IO或标准IO对文件进行 open()/fopen() , read()/fread() , write()/fwrite() , close()/fclose() 操作。那么linux内核态怎么进行文件操作呢?

        linux内核态在 /kernel/include/linux/fs.h 中提供了有相对应的函数供我们对文件进行IO操作。

功能

函数原型

打开文件

struct file *filp_open(const char *filename, int flags, int mode)

读文件

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)

关闭文件

int filp_close(struct file *filp, fl_owner_t id)

一、函数定义

1、filp_open()函数

struct file *filp_open(const char *filename, int flags, umode_t mode)

功能:打开文件

参数:

  • filename:要打开的文件的路径。
  • flags:文件的读写模式。常用的值有 O_RDONLY , O_WDONLY , O_RDWR , O_CREAT。这个参数的值与文件IO中的一样,它们被定义在 /kernel/include/uapi/asm-generic/fcntl.h 中。
  • mode:文件的权限

返回值:指向所打开文件的结构体指针。

2、filp_close()函数

int filp_close(struct file *filp, fl_owner_t id)

功能:关闭文件

参数:

  • filp:文件句柄
  • id:一般填0即可

返回值:0表示成功关闭。

3、vfs_read()函数

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

功能:读文件

参数:

  • file:文件句柄
  • buf:存放所读取的内容的数组。

注意:使用在内核态申请的字符数组,则要在调用这个函数之前先执行一下以下代码:

mm_segment_t old_fs;

old_fs = get_fs();

set_fs(KERNEL_DS);

/* vfs_read/vfs_write 操作相关代码 */

/* ... ... */

set_fs(old_fs);

  • count:期望读取的最大大小
  • pos:读取位置

返回值:实际读取到的数据大小

4、vfs_write()函数

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

与 vfs_read() 类似,就不再赘述了。

二、示例

#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/kthread.h>
#include <linux/err.h>
#include <linux/delay.h>
#include <linux/gfp.h>
#include <linux/file.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/syscalls.h>

#include <linux/slab.h>
#include <asm/segment.h>
#include <linux/mm.h>

#define FILE_PATH   "/dev/mmcblk0p9"         //表示 animation.yuv 文件分区
#define YUV420_SIZE   (384 * 288 * 3 / 2)    //384 * 288 yuv420图片的大小

static struct task_struct *animation_thread;

/* 内核态将图片文件读出,并写入DDR显存中 */
static int animation_work_thread(void *arg)
{
    unsigned int volatile *pVoAddr;
    struct file *fp;
    char *buff_animation;
    loff_t pos;
    mm_segment_t fs;
    int i;
    int flag = 0;

/* 1.打开分区文件 */
    fp = filp_open(FILE_PATH, O_RDONLY, 0);            //打开emmc分区
    if (IS_ERR(fp)){
        printk("filp_open error\n");
        return -1;
    }
    
    /* 一般系统调用会要求你使用的缓冲区不能在内核区。这个可以用set_fs()、get_fs()来解决 */
    fs = get_fs();
    set_fs(KERNEL_DS); 
    
    buff_animation = (char *)kzalloc(YUV420_SIZE, GFP_KERNEL);        //分配内存1
    if (!buff_animation)
        return -ENOMEM;

    pVoAddr = (unsigned int volatile *) phys_to_virt(0x22400000);     //物理地址映射为虚拟地址
    
    /* 循环显示动画 */
    while(1)
    {
        pos = 0;
        for(i = 0; i < 75; i++)            //轮询显示75张图
        {   
            pos = i * YUV420_SIZE;
            vfs_read(fp, buff_animation, YUV420_SIZE, &pos);

            memcpy(pVoAddr, buff_animation, YUV420_SIZE);            //数据拷贝到VO 显存

            msleep(50);
        }
    }

exit:
    kfree(buff_animation);     //释放内存  
    set_fs(fs);
    filp_close(fp, NULL);        //关闭文件
}


/* 创建线程 */
static int __init animation_init(void)
{
    /* 内核态创建线程 */
    animation_thread = kthread_run(animation_work_thread, NULL, "animation_thread");        
    if(!animation_thread) {
        printk("%s,  %s,  %d\n", __FILE__, __func__, __LINE__);
        return -EINVAL;
    }

    return 0;  
}

late_initcall(animation_init);     //arch_initcall 内核启动后自动调用 animation_init()函数

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值