将数据写到page cache
写文件的时候其实是通过文件系统写到page cache中,然后再由相应的线程在适当的时机将page cache中的数据写到磁盘中。
//fs/fat/file.c
const struct file_operations fat_file_operations = {
...
.aio_write = generic_file_aio_write,
...
};
//mm/filemap.c
generic_file_aio_write
__generic_file_aio_write
generic_file_buffered_write
generic_perform_write
a_ops->write_begin
iov_iter_copy_from_user_atomic(page, i, offset, bytes)
a_ops->write_end
通过sync系统调用将page cache写到磁盘中
//fs/fat/file.c
const struct file_operations fat_file_operations = {
...
.fsync = fat_file_fsync,
...
};
fat_file_fsync
generic_file_fsync
sync_inode_metadata
sync_inode
writeback_single_inode
__writeback_single_inode
do_writepages
mapping->a_ops->writepages
write_inode
通过回写线程bdi_writeback将page cache写到磁盘中
并不是很确定是内核中的回写线程还是用户空间的回写线程,有待研究一下!!!
//mm/backing_dev.c
bdi_init
bdi_wb_init
INIT_DELAYED_WORK(&wb->dwork, bdi_writeback_workfn);
bdi_writeback_workfn
wb_do_writeback
wb_writeback
writeback_sb_inodes
__writeback_single_inode
do_writepages
mapping->a_ops->writepages
write_inode
在这里初始化的时候安装了回写work,并且work的回调函数和前面系统sync系统调用一样最终都会调用__writeback_single_inode来回写page cache
那在哪里调度这个work的呢,需要研究一下,究竟是内核的timer还是用户空间的线程,不是很确定。 只要一调用bdi_queue_work这个函数就会调用work对应的回调函数。