本博客主要阐述最新内核(linux-3.12)的文件系统预读及时的设计和实现,可能有理解不全面的地方,望各位能多多指教。
所谓预读,是指文件系统为应用程序一次读出比预期更多的文件内容并缓存在page cache中,这样下一次读请求到来时部分页面直接从page cache读取即可。当然,这个细节对应用程序透明,应用程序可能的感觉唯一就是下次读的速度会更快,当然这是好事。
由于应用程序的访问行为存在多样性加上作者对预读的把握不是非常深入,因此,难免存在不是非常精确的地方,望多赐教。我们会通过设置几个情境来分析预读的逻辑。
情境1
// 事例代码
{
...
f = open("file", ....);
ret = read(f, buf, 4096);
ret = read(f, buf, 2 * 4096);
ret = read(f, buf, 4 * 4096);
...
}
该场景非常简单:打开文件,共进行三次读(且是顺序读),那让我们看看操作系统是如何对文件进行预读的。
Read 1
第一次进入内核读处理流程时,在page cache中查找该offset对应的页面是否缓存,因为首次读,缓存未命中,触发一次同步预读:static void do_generic_file_read(struct file *filp, loff_t *ppos,read_descriptor_t *desc, read_actor_t actor)
{
......
for (;;) {
......
cond_resched();
find_page:
// 如果没有找到,启动同步预读
page = find_get_page(mapping, index);
if (!page) {
page_cache_sync_readahead(mapping,ra, filp,index, last_index - index);
该同步预读逻辑最终进入如下预读逻辑:
// 注意: