📄 filemap.c.txt
字号:
any problems,send mails to sindybear@163.com
相关文件
/fs/buffer.c
(1)struct page * find_or_create_page(struct address_space *mapping, unsigned long index, unsigned int gfp_mask)
page = __find_lock_page_helper(mapping, index, *hash); //先试图照一个页面
if (!page) {
struct page *newpage = alloc_page(gfp_mask); //如果没有找到,就生成一个
***************************文件的读写****************************************
系统的读写都是以页为单位的。如果要写一整页的话,没有什么问题,但是如果要写一个页的一部分,
则要先从磁盘上读出这部分数据,然后将信数据复制到页中,然后将页置为dirty,交给系统写到磁盘上。
generic_file_write(struct file *file,const char *buf,size_t count, loff_t *ppos)
struct address_space *mapping = file->f_dentry->d_inode->i_mapping; //得到该文件的inode节点的mapping
//循环对buf进行处理
do {
//得到一个缓冲页,先在cache中寻找,如果找不到,分配一个新的,特别要注意
//这里的mapping,也就是关于这个inode节点的页处理函数就传递给这个页,
//也就是说,分配的这个页就按照mapping中所指示的文件系统所给定的readpage,writepage
//函数进行这个页面的读写操作
page = __grab_cache_page(mapping, index, &cached_page);
kaddr = kmap(page); //取出地址映射,为复制数据做准备
//调用相应文件系统的prepare_write函数进行一些准备工作,正如前面所说
//例如,要写页的一部分的话,要先将页面从磁盘上读出来,诸如此类的事情
status = mapping->a_ops->prepare_write(file, page, offset, offset+bytes);
//将用户态的数据复制到页面中
page_fault = __copy_from_user(kaddr+offset, buf, bytes);
//刷新页面
flush_dcache_page(page);
//调用相应文件系统的commit_write函数进行真正的读写操作
status = mapping->a_ops->commit_write(file, page, offset, offset+bytes);
} while (count);
…… //进行页面地址解除映射等工作
*****************************************************************************
*****************************文件读写页面的分配******************************
static inline struct page * __grab_cache_page(struct address_space *mapping,unsigned long index, struct page **cached_page)
struct page *page, **hash = page_hash(mapping, index); //得到哈希表的入口
repeat:
page = __find_lock_page(mapping, index, hash); //在哈西表中先寻找
if (!page) {
if (!*cached_page) {
*cached_page = page_cache_alloc(mapping); //如果没有找到,就非配一个
if (!*cached_page)
return NULL;
}
page = *cached_page;
if (add_to_page_cache_unique(page, mapping, index, hash))//将这个页面加入到哈希表中
goto repeat;
*cached_page = NULL;
}
return page;
int add_to_page_cache_unique(struct page * page,struct address_space *mapping, unsigned long offset,struct page **hash)
spin_lock(&pagecache_lock); //加锁,保护页缓冲哈希表
alias = __find_page_nolock(mapping, offset, *hash); //由于上面的操作可能引起调度,在检查一遍
if (!alias)
__add_to_page_cache(page,mapping,offset,hash); //确信哈希表中没有这一项,将这个页面插入到表中
spin_unlock(&pagecache_lock); //解锁
lru_cache_add(page); //加入到lru列表中
static inline void __add_to_page_cache(struct page * page,struct address_space *mapping, unsigned long offset,struct page **hash)
…… //进行常规的页面设置
page_cache_get(page); //page的引用计数count加一
add_page_to_inode_queue(mapping, page); //使用相应inode中的mapping对页面进行初始化
add_page_to_hash_queue(page, hash); //将页面加入到哈希表中
static inline void add_page_to_inode_queue(struct address_space *mapping, struct page * page)
struct list_head *head = &mapping->clean_pages;
mapping->nrpages++;
list_add(&page->list, head); //将这个信分配的叶面加入到clean队列中
page->mapping = mapping; //将页面的mapping域设置为相应文件系统的mapping域,
//这样就可以使用这个文件系统的writepage等的函数设置
//来进行文件的读写等操作
*****************************************************************************
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -