Linux VFS机制简析(二) (2)

sync_page:VM调用,用于通知后端存储处理该page的I/O。该page所属address space的其他Pages的I/O也可能被处理。该函数是可选的,仅用于等待PG_Writeback的page处理完成。

writepages:VM调用,将address space里所有Dirty的pages写入后端存储。如果wbc->sync_mode是WBC_SYNC_ALL,则writeback_control会选取一个范围的pages必须写入。如果是WBC_SYNC_NONE,则根据参数nr_to_write尽可能写入这么多pages。如果没有设置,则默认调用mpage_writepages()。

set_page_dirty:VM调用,用于设置page为dirty。通常用于address space里有新的数据写入,如memory mapping的page被修改。该函数将设置PageDirty标记,并在Radix树里设置PAGECACHE_TAG_DIRTY标识。

readpages:VM调用,用于读取address space里的指定pages。主要是通过调用readpage将一组pages读取。通常用于预读,因此读取失败的错误码可能会被忽略。

write_begin:由通用的buffered写流程调用,写入len长度数据到文件的offset处。address space可能需要申请额外的存储空间来保证写操作可以完成,或者需要从后端存储读取不在缓存里的pages。该函数返回的pagep要处于locked状态,调用者将直接写入数据。返回参数fsdata用于私有数据指针,它将传递给write_end函数。如果函数返回<0,则write_end将不会调用。
write_end:数据拷贝到write_begin返回的page后,调用write_end将page unlock,递减引用计数并更新i_size字段。

bmap:VFS调用用于映射逻辑块的偏移和物理块编号。该方法由FIBMAP ioctl使用,并且是swap文件。swap系统不直接进入文件系统,而是通过BMAP方式建立内存地址和文件的块映射,然后直接使用内存地址。

invalidatepage:如果设置了PagePrivate,则当Page部分或者全部从address space里删除时调用该方法。通常是因为address space里执行了一个截断或者是失效所有数据。和page关联的私有信息需要更新,或者直接被释放(如果失效的offset为0的话,整个page将被释放)。

releasepage:用于将PagePrivate pages释放,它将把私有数据释放,然后清除PagePrivate标识。releasepage有两种使用场景,一是VM发现没有引用计数的clean page,想将其变成free page。通过调用releasepage将其从address space里摘掉变为clean page。二是有invalid请求需要将address space里的部分或全部pages失效。通常是fadvice系统调用或者文件系统自己认为缓存里的数据已经不是最新的了,此时通过调用invalidate_inode_pages2()将pages释放。调动该函数前,需要保证pages已经是invalidate的。如果释放私有数据失败,则需要在返回错误之前将PageUptodate清除。

freepage:用于将不在pagecache里的page释放,page必须不属于任何address space。通常有内存回收处理程序调用。
direct_IO:由通用读写流程调用,绕过pagecache,DIO方式读取数据。
get_xip_page:VM调用,将block number转换为page。支持XIP(execute in place)的文件系统需要实现该函数。
migrate_page:在old page和new page之间迁移数据,通常用于内存整理(减少碎片)。迁移时需要将私有数据和引用一起迁移。
launder_page:在free之前调用,用于writeback dirty page。为了防止再次被设置dirty,操作过程中持有page lock。
error_remove_page:用于内存分配失败的处理,如果address space支持truncation,通常设置为generic_error_remove_page()。
swap_activate and swap_deactivate:用于swapon在一个文件上时,分配空间并将block信息保存在内存中。以及swapoff时释放空间。

File

一个File数据结构代表一个进程里打开的一个文件。所以File结构是跟进程相关的,不同的进程打开同一个文件会在每个进程里都有一个File对象,对应到进程的文件句柄。
同一个文件File结构指向的inode是同一个,所以通过pagecache缓存进行数据读写的时候,使用的是inode里同一个address space,保证文件数据在不同进程里的一致性。

struct file_operations

struct file_operations的定义如下:

struct file_operations { struct module *owner; loff_t (*llseek) (struct file *, loff_t, int); ssize_t (*read) (struct file *, char __user *, size_t, loff_t *); ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *); ssize_t (*aio_read) (struct kiocb *, const struct iovec *, unsigned long, loff_t); ssize_t (*aio_write) (struct kiocb *, const struct iovec *, unsigned long, loff_t); int (*readdir) (struct file *, void *, filldir_t); unsigned int (*poll) (struct file *, struct poll_table_struct *); long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long); long (*compat_ioctl) (struct file *, unsigned int, unsigned long); int (*mmap) (struct file *, struct vm_area_struct *); int (*open) (struct inode *, struct file *); int (*flush) (struct file *); int (*release) (struct inode *, struct file *); int (*fsync) (struct file *, loff_t, loff_t, int datasync); int (*aio_fsync) (struct kiocb *, int datasync); int (*fasync) (int, struct file *, int); int (*lock) (struct file *, int, struct file_lock *); ssize_t (*readv) (struct file *, const struct iovec *, unsigned long, loff_t *); ssize_t (*writev) (struct file *, const struct iovec *, unsigned long, loff_t *); ssize_t (*sendfile) (struct file *, loff_t *, size_t, read_actor_t, void *); ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int); unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long); int (*check_flags)(int); int (*flock) (struct file *, int, struct file_lock *); ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, size_t, unsigned int); ssize_t (*splice_read)(struct file *, struct pipe_inode_info *, size_t, unsigned int); int (*setlease)(struct file *, long arg, struct file_lock **); long (*fallocate)(struct file *, int mode, loff_t offset, loff_t len); };

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zwwysp.html