本文主要参考《深入理解Linux内核》,结合2.6.11版的内核代码,分析内核文件子系统中的页高速缓存处理函数。
注意:
1、 不描述内核同步、错误处理、参数合法性验证相关的内容
2、 源码摘自Linux内核2.6.11 stable版,获取命令:
git clone
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git
cd ./linux-stable/
git checkout linux-2.6.11.y
3、 阅读本文请结合《深入理解Linux内核》第三版相关章节
4、 本文会不定时更新
函数调用结构
公共函数
1、find_get_page
功能:
调用函数radix_tree_lookup在address_space 的radix_tree_root中查找页,找到则增加页的引用计数并返回,未找到返回NULL
源码:
/*
* a rather lightweight function, finding and getting a reference to a
* hashed page atomically.
*/
struct page * find_get_page(struct address_space *mapping, unsigned long offset)
{
struct page *page;
spin_lock_irq(&mapping->tree_lock);
page = radix_tree_lookup(&mapping->page_tree, offset);
if (page)
page_cache_get(page);
spin_unlock_irq(&mapping->tree_lock);
return page;
}
2、find_get_pages
功能:
调用函数radix_tree_gang_lookup从树中查找nr_pages个非空页,并增加找到页的引用计数
源码:
/**
* find_get_pages - gang pagecache lookup
* @mapping: The address_space to search
* @start: The starting page index
* @nr_pages: The maximum number of pages
* @pages: Where the resulting pages are placed
*
* find_get_pages() will search for and return a group of up to
* @nr_pages pages in the mapping. The pages are placed at @pages.
* find_get_pages() takes a reference against the returned pages.
*
* The search returns a group of mapping-contiguous pages with ascending
* indexes. There may be holes in the indices due to not-present pages.
*
* find_get_pages() returns the number of pages which were found.
*/
unsigned find_get_pages(struct address_space *mapping, pgoff_t start,
unsigned int nr_pages, struct page **pages)
{
unsigned int i;
unsigned int ret;
spin_lock_irq(&mapping->tree_lock);
ret = radix_tree_gang_lookup(&mapping->page_tree,
(void **)pages, start, nr_pages);
for (i = 0; i < ret; i++)
page_cache_get(pages[i]);
spin_unlock_irq(&mapping->tree_lock);
return