美文网首页
内核读写磁盘文件

内核读写磁盘文件

作者: 网路元素 | 来源:发表于2019-10-26 07:33 被阅读0次

    在用户态,即我们一般编写的C语言程序中,可以使用open、close、read、write等系统调用对磁盘文件进行操作,那么在内核态呢?同样有相应的函数可以使用,而这些函数却是open这些系统调用会使用到的,故而我们还是在内核面向应用的层级进入,实现对磁盘文件的操作。关于如何从open一层层往下找到我们即将要使用的函数过程就不说了,下面直接给出我们用到的函数定义或原型信息,都在include/linux/fs.h文件中有声明,分别在fs/open.c和fs/read_write.c实现下面两类操作函数:

    1.打开、关闭文件

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

    其中,filename就是文件名(包含完整路径),flags必须包含O_RDONLY、O_WRONLY或O_RDWR其中之一,而mode只有在flags包含O_CREAT时才有作用,表示打开的文件不存在就进行创建时该文件的访问权限,可以是S_IRWXU、S_IRUSR或S_IWUSR等的组合,对于O_和S_开头的这些宏说明可使用man 2 open命令查看,而这些宏则分别在内核include/uapi/asm-generic/fcntl.h和include/uapi/linux/stat.h文件中定义。

    int filp_close(struct file *filp, fl_owner_t id) ;

    其中,filp指针就是filp_open的返回值,id是POSIX线程的ID,而我们在内核态中操作,暂不需要用到,故一般设置为NULL即可。

    2.读写文件

    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) ;

    其中,file指针使用filp_open的返回值,buf是用户空间的内存(读写数据存放位置),count是读写多少单位(字节)的数据,pos表示当前文件读写所处于的偏移位置。

    相信大家都注意到了,这儿存取用到的buf是用户空间的内存,但等会我们是在内核里调用到,并且传入的是在内核态申请的空间,这样操作肯定没权限,在内核include/asm-generic/uaccess.h文件里有如下定义:

    #define MAKE_MM_SEG(s) ((mm_segment_t) { (s) })
    #ifndef KERNEL_DS
    #define KERNEL_DS MAKE_MM_SEG(~0UL)
    #endif
    #ifndef USER_DS
    #define USER_DS MAKE_MM_SEG(TASK_SIZE - 1)
    #endif
    #ifndef get_fs
    #define get_ds() (KERNEL_DS)
    #define get_fs() (current_thread_info()->addr_limit)
    static inline void set_fs(mm_segment_t fs)
    {
            current_thread_info()->addr_limit = fs;
    }
    #endif

    其中, mm_segment_t在arch/x86/include/asm/processor.h文件中有如下定义:

    typedef struct {
            unsigned long seg;
    } mm_segment_t;

    我们从set_fs和get_fs可以看到其对当前线程的地址权限标志作了修改,所以等会我们在内核分配好空间,然后使用vfs_read或vfs_write进行操作时,要先使用get_fs保存状态,再使用set_fs(KERNEL_DS)修改下地址限制,而使用完成后再使用set_fs()恢复保存的状态,接下来通过实例学习下这操作的鬼魅吧:

    #include <linux/init.h>
    #include <linux/module.h>
    #include <linux/fs.h>
    #include <asm/uaccess.h>

    #define SLAM_FILE_PATH "/home/xinu/slam.txt"

    static char wbuf[] = "Hello slam-xinu";
    static char rbuf[128];

    static int vfs_operate_init(void)
    {
            struct file * fp;
            mm_segment_t cur_mm_seg;
            loff_t fpos = 0;
            printk("<xinu>in %s!\n",__func__);

            fp = filp_open(SLAM_FILE_PATH, O_RDWR | O_CREAT, 0644);
            if (IS_ERR(fp)) {
                    printk("<xinu>filp_open error\n");
                    return -1;
            }

            cur_mm_seg = get_fs();
            set_fs(KERNEL_DS);
            vfs_write(fp, wbuf, sizeof(wbuf), &fpos);
            fpos = 0;
            vfs_read(fp, rbuf, sizeof(rbuf), &fpos);
            printk("<xinu>read content: %s\n", rbuf);
            set_fs(cur_mm_seg);
            filp_close(fp, NULL);

            return 0;
    }

    static void vfs_operate_exit(void)
    {
            printk("Bye %s!\n", __func__);
    }

    module_init(vfs_operate_init);
    module_exit(vfs_operate_exit);

    MODULE_LICENSE("GPL");

    相应的Makefile文件内容如下:

    obj-m += vfs_operate_example.o

    CUR_PATH:=$(shell pwd)
    LINUX_KERNEL_PATH:=/home/xinu/linux-3.13.6

    all:
            make -C $(LINUX_KERNEL_PATH) M=$(CUR_PATH) modules

    clean:
            make -C $(LINUX_KERNEL_PATH) M=$(CUR_PATH) clean

    对应的源码文件目录树如下:

    /home/xinu/xinu/linux_kernel_driver_l1/vfs_operate_example/
    ├── Makefile
    └── vfs_operate_example.c

    该模块在/home/xinu目录下创建slam.txt文件,并往里写入Hello slam-xinu字符串,然后读取打印出来,而该文件对应的信息如下:

    xinu@slam:~/$ ls -l /home/xinu/slam.txt
    -rw-r--r-- 1 root root 16 May 22 18:37 /home/xinu/slam.txt
    xinu@slam:~/$ file /home/xinu/slam.txt
    /home/xinu/slam.txt: ASCII text, with no line terminators

    从上面显示该文件没有行终止符,所以打开文件时会看到怪异的结束符号。

    参考网址:

    http://blog.csdn.net/tommy_wxie/article/details/8193954
    http://blog.csdn.net/tommy_wxie/article/details/8194276
    http://blog.csdn.net/proware/article/details/5959842
    http://blog.chinaunix.net/uid-712024-id-2678927.html

    相关文章

      网友评论

          本文标题:内核读写磁盘文件

          本文链接:https://www.haomeiwen.com/subject/wkxryctx.html