本章将介绍write()系统调用的过程。和第二章read()一样我们将从file_operations.write()开始。
1. write():从file operation到page cache
file_operations.write()的核心函数是generic_perform_write()。
大部分文件系统的file_operations.write()最后都会调用generic_perform-write()这个通用的函数。generic_perform-write()的实现方法体现了Linux文件系统write()的典型流程。
这个函数的流程如下图:
从上图可以看到以下几个要点:
- Write是一个一个Page Write的
- 大部分实质性的工作都是在aops.write_begin()和aops.write_end()里做的。
- write_begin()之后page就ready了,用户的数据就可以copy到page中了。
write_begin()的作用主要是:找到(创建)page->找到(创建)bh->map buffer。流程如下图所示:
2. write():从page cache到writeback queue
用户的数据已经写到page cache中去了, 将page cache真正写到block device的过程比read()复杂,因为当中有writeback的机制。整个writeback机制将在下一章做详细介绍。这里只介绍page cache是怎样交给writeback queue的,这个过程就是在aops.write_end()里完成的。要写的page加到了writeback queue后将有writeback thread将其真正写到block device上。
下图是大部分aops.write_end()使用的典型函数generic_write_end()的流程,这个流程的调用层次比较深,大致可分为三个层次:generic_write_end() -> __block_commit_write() ->__mark_inode_dirty()。下面也是分三张图来说明他们的流程和作用。
2.1 顶层write_end的典型函数:generic_write_end()
2.2 generic_write_end()主要调用了__block_commit_write()
2.3 将dirty inode放到writeback queue的关键动作在__mark_inode_diry()里