免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1520 | 回复: 1
打印 上一主题 下一主题

2.4.0版本page结构使用计数的疑问 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-12-12 21:54 |只看该作者 |倒序浏览
《情景分析》中,2.4.0中,说一个page结构时,有且并且只有一个进程映射到这个页面时,使用计数会是2
但是,在缺页异常处理中,分配一个匿名内存页时,这个计数却只会是alloc_page()中的初始值1,再加1的地方在哪了?
  1. /*
  2. * This only needs the MM semaphore
  3. */
  4. static int do_anonymous_page(struct mm_struct * mm, struct vm_area_struct * vma, pte_t *page_table, int write_access, unsigned long addr)
  5. {
  6.         struct page *page = NULL;
  7.         pte_t entry = pte_wrprotect(mk_pte(ZERO_PAGE(addr), vma->vm_page_prot));
  8.         if (write_access) {
  9.                 page = alloc_page(GFP_HIGHUSER);
  10.                 if (!page)
  11.                         return -1;
  12.                 clear_user_highpage(page, addr);
  13.                 entry = pte_mkwrite(pte_mkdirty(mk_pte(page, vma->vm_page_prot)));
  14.                 mm->rss++;
  15.                 flush_page_to_ram(page);
  16.         }
  17.         set_pte(page_table, entry);
  18.         /* No need to invalidate - it was non-present before */
  19.         update_mmu_cache(vma, addr, entry);
  20.         return 1;        /* Minor fault */
  21. }
复制代码

在alloc_page()中:
  1. set_page_count(page, 1);
复制代码


同时在缺页异常中,是因为COW而调用do_wp_page()函数,新分配一个page页,从旧页拷贝数据到新页,再释放旧页,也不会增加新页的使用计数,这是为什么了?

  1. static int do_wp_page(struct mm_struct *mm, struct vm_area_struct * vma,
  2.         unsigned long address, pte_t *page_table, pte_t pte)
  3. {
  4.         struct page *old_page, *new_page;
  5. /*
  6.          * Ok, we need to copy. Oh, well..
  7.          */
  8.         spin_unlock(&mm->page_table_lock);
  9.         new_page = page_cache_alloc();
  10.         if (!new_page)
  11.                 return -1;
  12.         spin_lock(&mm->page_table_lock);

  13.         /*
  14.          * Re-check the pte - we dropped the lock
  15.          */
  16.         if (pte_same(*page_table, pte)) {
  17.                 if (PageReserved(old_page))
  18.                         ++mm->rss;
  19.                 break_cow(vma, old_page, new_page, address, page_table);

  20.                 /* Free the old page.. */
  21.                 new_page = old_page;
  22.         }
  23.         spin_unlock(&mm->page_table_lock);
  24.         page_cache_release(new_page);
  25.         return 1;        /* Minor fault */

  26. bad_wp_page:
  27.         spin_unlock(&mm->page_table_lock);
  28.         printk("do_wp_page: bogus page at address %08lx (page 0x%lx)\n",address,(unsigned long)old_page);
  29.         return -1;
  30. }
复制代码


谢谢,:)

论坛徽章:
0
2 [报告]
发表于 2009-12-12 22:11 |只看该作者
而在2.6.12的do_wp_page中,则在分配page页后,增加使用计数的地方

  1. static int do_wp_page(struct mm_struct *mm, struct vm_area_struct * vma,
  2.         unsigned long address, pte_t *page_table, pmd_t *pmd, pte_t pte)
  3. {
  4.         struct page *old_page, *new_page;
  5.         unsigned long pfn = pte_pfn(pte);
  6.         pte_t entry;
  7. /*
  8.          * Ok, we need to copy. Oh, well..
  9.          */
  10.         if (!PageReserved(old_page))
  11.                 page_cache_get(old_page);
  12.         spin_unlock(&mm->page_table_lock);

  13.         if (unlikely(anon_vma_prepare(vma)))
  14.                 goto no_new_page;
  15.         if (old_page == ZERO_PAGE(address)) {
  16.                 new_page = alloc_zeroed_user_highpage(vma, address);
  17.                 if (!new_page)
  18.                         goto no_new_page;
  19.         } else {
  20.                 new_page = alloc_page_vma(GFP_HIGHUSER, vma, address);
  21.                 if (!new_page)
  22.                         goto no_new_page;
  23.                 copy_user_highpage(new_page, old_page, address);
  24.         }
  25.         /*
  26.          * Re-check the pte - we dropped the lock
  27.          */
  28.         spin_lock(&mm->page_table_lock);
  29.         page_table = pte_offset_map(pmd, address);
  30.         if (likely(pte_same(*page_table, pte))) {
  31.                 if (PageAnon(old_page))
  32.                         dec_mm_counter(mm, anon_rss);
  33.                 if (PageReserved(old_page))
  34.                         inc_mm_counter(mm, rss);
  35.                 else
  36.                         page_remove_rmap(old_page);
  37.                 flush_cache_page(vma, address, pfn);
  38.                 break_cow(vma, new_page, address, page_table);
  39.                 [color=Red]lru_cache_add_active(new_page);[/color]
  40.                 page_add_anon_rmap(new_page, vma, address);

  41.                 /* Free the old page.. */
  42.                 new_page = old_page;
  43.         }
  44.         pte_unmap(page_table);
  45.         page_cache_release(new_page);
  46.         page_cache_release(old_page);
  47.         spin_unlock(&mm->page_table_lock);
  48.         return VM_FAULT_MINOR;

  49. no_new_page:
  50.         page_cache_release(old_page);
  51.         return VM_FAULT_OOM;
  52. }
  53. void fastcall lru_cache_add_active(struct page *page)
  54. {
  55.         struct pagevec *pvec = &get_cpu_var(lru_add_active_pvecs);

  56.         [color=Red]page_cache_get(page);[/color]
  57.         if (!pagevec_add(pvec, page))
  58.                 __pagevec_lru_add_active(pvec);
  59.         put_cpu_var(lru_add_active_pvecs);
  60. }
复制代码
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP