美文网首页
浅尝辄止86-NTFS文件系统1-内核2-读文件0

浅尝辄止86-NTFS文件系统1-内核2-读文件0

作者: 阿棍儿_Leon | 来源:发表于2019-03-01 20:59 被阅读0次

    与FAT32一样,NTFS也有自己的构建inode的方法,这点也没什么好说的,就是一个生成文件编号的算法,只要不重复,怎么生都行。
    写文件也是类似的,也是先如page,然后再由后备设备刷到磁盘上。
    在NTFS文件系统上就看看怎么读吧,因为它的写功能通常是关闭的,开起来能不能用也不知道。

    读文件

    了解文件操作,关键点是文件系统的struct file_operations变量的赋值。NTFS的在kernel/fs/ntfs/file.cntfs_file_open里面也是接到VFS的open,NTFS关于open的自定义操作很少,就不研究了。

    const struct file_operations ntfs_file_ops = {
        .llseek     = generic_file_llseek,   /* Seek inside file. */
        .read       = new_sync_read,     /* Read from file. */
        .read_iter  = generic_file_read_iter, /* Async read from file. */
    #ifdef NTFS_RW
        .write      = do_sync_write,     /* Write to file. */
        .aio_write  = ntfs_file_aio_write,   /* Async write to file. */
        /*.release  = ,*/            /* Last file is closed.  See
                                fs/ext2/file.c::
                                ext2_release_file() for
                                how to use this to discard
                                preallocated space for
                                write opened files. */
        .fsync      = ntfs_file_fsync,   /* Sync a file to disk. */
        /*.aio_fsync    = ,*/            /* Sync all outstanding async
                                i/o operations on a
                                kiocb. */
    #endif /* NTFS_RW */
        /*.ioctl    = ,*/            /* Perform function on the
                                mounted filesystem. */
        .mmap       = generic_file_mmap,     /* Mmap file. */
        .open       = ntfs_file_open,    /* Open file. */
        .splice_read    = generic_file_splice_read /* Zero-copy data send with
                                the data source being on
                                the ntfs partition.  We do
                                not need to care about the
                                data destination. */
        /*.sendpage = ,*/            /* Zero-copy data send with
                                the data destination being
                                on the ntfs partition.  We
                                do not need to care about
                                the data source. */
    };
    

    new_sync_read是读操作,仔细看一下可知,它实际上用filp->f_op->read_iter调用的是.read_iter=generic_file_read_iter这个函数。

    ssize_t new_sync_read(struct file *filp, char __user *buf, size_t len, loff_t *ppos)
    {
        struct iovec iov = { .iov_base = buf, .iov_len = len };
        struct kiocb kiocb;
        struct iov_iter iter;
        ssize_t ret;
    
        init_sync_kiocb(&kiocb, filp);
        kiocb.ki_pos = *ppos;
        kiocb.ki_nbytes = len;
        iov_iter_init(&iter, READ, &iov, 1, len);
    
        ret = filp->f_op->read_iter(&kiocb, &iter);
        if (-EIOCBQUEUED == ret)
            ret = wait_on_sync_kiocb(&kiocb);
        *ppos = kiocb.ki_pos;
        return ret;
    }
    

    然后到do_generic_file_read里面的copy_page_to_iter,一个page就被拷贝到用户的buffer了。
    当然,在此之前要先readpage,要让page的内容与磁盘内容一致,这样拷贝给用户的才是磁盘内容。readpage的出发点当然在do_generic_file_read里面,但是我们其实可以不分析这里,因为关于文件的page操作每个文件系统都要定义清楚,不管这个函数怎么执行,都要调用到那些操作。与FAT32类似,那些操作就是一个struct address_space_operations变量,就是const struct address_space_operations ntfs_normal_aops,在kernel/fs/ntfs/aops.c

    const struct address_space_operations ntfs_normal_aops = {
        .readpage   = ntfs_readpage,
    #ifdef NTFS_RW
        .writepage  = ntfs_writepage,
        .set_page_dirty = __set_page_dirty_buffers,
    #endif /* NTFS_RW */
        .bmap       = ntfs_bmap,
        .migratepage    = buffer_migrate_page,
        .is_partially_uptodate = block_is_partially_uptodate,
        .error_remove_page = generic_error_remove_page,
    };
    

    下次我们要分析一下ntfs_readpage这个函数。

    相关文章

      网友评论

          本文标题:浅尝辄止86-NTFS文件系统1-内核2-读文件0

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