Chinaunix首页 | 论坛 | 博客
  • 博客访问: 96849
  • 博文数量: 29
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 10
  • 用 户 组: 普通用户
  • 注册时间: 2014-09-01 19:43
文章分类
文章存档

2017年(4)

2015年(24)

2014年(1)

我的朋友

分类: LINUX

2015-07-11 13:57:24

Read读操作

 

// page 存放page cache中找到的页面

// cached_page存放不存在page cache时分配的页面

 

do_generic_file_read

 

。。。。。。。。。。。。。。。。。。。。。。。。。。

       struct page *cached_page;

  。。。。。。。。。。。。。。。。。。。。。。。。。。

       cached_page = NULL;

  。。。。。。。。。。。。。。。。。。。。。。。。。。

 

for (;;) {

              struct page *page, **hash;

。。。。。。。。。。。。。。。。。。。。。。。。。。

 

for循环中找高速缓存中的页面,找不到跳转

*************************************************************

//page_hash_table找到其对应的杂凑队列

         hash = page_hash(mapping, index);

 

//自旋锁

         spin_lock(&pagecache_lock);

 

//搜索此队列,找到该页面page结构

         page = __find_page_nolock(mapping, index, *hash);

 

问题1:比较写操作中,第一,他没有在这一步之前上自旋锁;第二他在队列中搜索的是用__find_lock_page,有何不同?

 

//没有在page cache中找到,跳到no_cached_page

         if (!page)

                goto no_cached_page;

*****************************************************************

 

 

no_cached_page处调用page_cache_alloc分配新页面,且调用__add_to_page_cache将新页面加入高速缓存,调用lru_cache_add将其加入LRU

*************************************************************

no_cached_page:

  。。。。。。。。。。。。。。。。。。。。。。。。。。

 

//页面没有缓存,分配新页面

         if (!cached_page) {

 

//解自旋锁

                spin_unlock(&pagecache_lock);

 

//分配建立一个缓冲页面(空白、空闲)

                cached_page = page_cache_alloc(mapping);

         。。。。。。。。。。。。。。。。。。。。。。。。。。

                }

 

//将新页面加入hash,有具体函数解析

page = cached_page;

         __add_to_page_cache(page, mapping, index, hash);

 

//解自旋锁

         spin_unlock(&pagecache_lock);

问题2:上一次已经解过自旋锁,而__add_to_page_cache并没有再次自旋锁,这里为什么还要解自旋锁呢?

 

//调用lru_cache_addpage增加到非活动链表(unactive_list)

         lru_cache_add(page);    

 

         cached_page = NULL;

 

//跳转到readpage

         goto readpage;

  }

*************************************************************

 

__add_to_page_cache解析

把新页面如何加入hash表,且这里关联设置了page标志

/*

 * This adds a page to the page cache, starting out as locked,

 * owned by us, but unreferenced, not uptodate and with no errors.

 */

static inline void __add_to_page_cache(struct page * page,       struct address_space *mapping, unsigned long offset, struct page **hash)

{

  unsigned long flags;

 

//PG_uptodatePG_errorPG_dirtyPG_referencedPG_arch_1PG_checked标志

  flags = page->flags & ~(1 << PG_uptodate | 1 << PG_error | 1 << PG_dirty | 1 << PG_referenced | 1 << PG_arch_1 | 1 << PG_checked);

 

//设置页框PG_locked标志,加以上表示页已经被加锁并存在与高速缓存中但还没有填充数据

  page->flags = flags | (1 << PG_locked);

 

//先增加页面引用计数

  page_cache_get(page);

 

//初始化index字段,表示含有数据的页在页的磁盘映像中的位置

  page->index = offset;

 

//调用add_page_to_inode_quequepage插入page cache对象的clean_pages

  add_page_to_inode_queue(mapping, page);

 

//调用add_page_to_hash_queuepage插入到散列表中

  add_page_to_hash_queue(page, hash);

}

 

 

 

Write写操作

// page 存放page cache中找到的页面

// cached_page存放不存在page cache时分配的页面

 

generic_file_write

 

。。。。。。。。。。。。。。。。。。。。。。。。。。

       struct page *cached_page;

  。。。。。。。。。。。。。。。。。。。。。。。。。。

       cached_page = NULL;

  。。。。。。。。。。。。。。。。。。。。。。。。。。

 

do {

      。。。。。。。。。。。。。。。。。。。。。。。。。。

              page = __grab_cache_page(mapping, index, &cached_page);

。。。。。。。。。。。。。。。。。。。。。。。。。。

              kaddr = kmap(page);

              status = mapping->a_ops->prepare_write(file, page, offset, offset+bytes);

              if (status)

                     goto sync_failure;

              page_fault = __copy_from_user(kaddr+offset, buf, bytes);

              flush_dcache_page(page);

 

                conditional_schedule();

 

              status = mapping->a_ops->commit_write(file, page, offset, offset+bytes);

 

       。。。。。。。。。。。。。。。。。。。。。。。。。。

              if (status >= 0) {

                     written += status;

                     count -= status;

                     pos += status;

                     buf += status;

。。。。。。。。。。。。。。。。。。。。。。。。。。

       } while (count);

 

__grab_cache_page解析

do循环调用的函数__grab_cache_page中把read的几个步骤综合起来,在页高速缓存中找页,没有找到分配新页以及将新页面加入hash

******************************************************

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);

*************************************************************

 

 

如果页没有缓存,调用page_cache_alloc分配新页面,且调用add_to_page_cache_unique 通过他来调用__add_to_page_cache将新页面加入高速缓存&调用lru_cache_add将其加入LRU

*************************************************************

 

  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;

}

*************************************************************

 

add_to_page_cache_unique解析

调用__add_to_page_cache将新页面加入高速缓存&调用lru_cache_add将其加入LRU

*************************************************************

 

int add_to_page_cache_unique(struct page * page,

  struct address_space *mapping, unsigned long offset,

  struct page **hash)

{

  int err;

  struct page *alias;

 

//自旋锁

  spin_lock(&pagecache_lock);

  alias = __find_page_nolock(mapping, offset, *hash);

 

问题3 这里为什么又要再一次__find_page_nolock呢?

我发现再每次__find_page_nolock前都需要自旋锁一次

  err = 1;

  if (!alias) {

         __add_to_page_cache(page,mapping,offset,hash);(见上面已分析)

         err = 0;

  }

 

  spin_unlock(&pagecache_lock);

  if (!err)

         lru_cache_add(page);

  return err;

}

 

 

 

//add_page_to_inode_queuepage插入page cache对象的clean_pages

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);

    page->mapping = mapping;

}

 

//add_page_to_hash_queuepage插入到散列表中

static void FASTCALL(add_page_to_hash_queue(struct page * page, struct page **p));

static void add_page_to_hash_queue(struct page * page, struct page **p)

{

    struct page *next = *p;

 

    *p = page;

    page->next_hash = next;

    page->pprev_hash = p;

    if (next)

           next->pprev_hash = &page->next_hash;

    if (page->buffers)

           PAGE_BUG(page);

    atomic_inc(&page_cache_size);

}

 

 

阅读(1339) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~