首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

缺页异常详解(8)

缺页异常详解(8)

/*返回不可写的页的页描述符,如果是COW的第一种情况即zero_pfn可读页,返回NULL,将进入下面的if流程;第二种情况即(父子进程)共享页将正常返回其页描述符*/         old_page = vm_normal_page(vma, address, orig_pte);
         if (!old_page) {
                   /*
                    * VM_MIXEDMAP !pfn_valid() case
                    *
                    * We should not cow pages in a shared writeable mapping.
                    * Just mark the pages writable as we can't do any dirty
                    * accounting on raw pfn maps.
                    */
                   /*如果这个vma是可写且共享的,跳到标号reuse,这就不会COW

否则跳到标号gotten*/

                   if ((vma->vm_flags & (VM_WRITE|VM_SHARED)) ==
                                          (VM_WRITE|VM_SHARED))
                            goto reuse;
                   goto gotten;
         }
         /*
          * Take out anonymous pages first, anonymous shared vmas are
          * not dirty accountable.
          */
/*下面的ifelse流程,都是为了尽可能不进行COW,它们试图进入标号reuse*/


         /*如果该页old_page是匿名页(由页描述符的mapping)

并且只有一个进程使用该页(reuse_swap_page,由页描述符的_mapcount值是否为0),那么不要搞什么COW了,这个进程就是可以使用该页*/

         if (PageAnon(old_page) && !PageKsm(old_page)) {
        /*排除其他进程在使用该页的情况,由页描述符的flag*/
                   if (!trylock_page(old_page)) {
                            page_cache_get(old_page);
                            pte_unmap_unlock(page_table, ptl);
                            lock_page(old_page);
                            page_table = pte_offset_map_lock(mm, pmd, address,
                                                                  &ptl);
                            if (!pte_same(*page_table, orig_pte)) {
                                     unlock_page(old_page);
                                     page_cache_release(old_page);
                                     goto unlock;
                            }
                            page_cache_release(old_page);
                   }
        /*判断该页描述符的_mapcount值是否为0*/
                   reuse = reuse_swap_page(old_page);
                   unlock_page(old_page);
         }
    /*如果vma是共享且可写,看看这种情况下有没有机会不COW*/
    else if (unlikely((vma->vm_flags & (VM_WRITE|VM_SHARED)) ==
                                               (VM_WRITE|VM_SHARED))) {
                   /*
                    * Only catch write-faults on shared writable pages,
                    * read-only shared pages can get COWed by
                    * get_user_pages(.write=1, .force=1).
                    */
                   if (vma->vm_ops && vma->vm_ops->page_mkwrite) {
                            struct vm_fault vmf;
                            int tmp;
                            vmf.virtual_address = (void __user *)(address &
                                                                           PAGE_MASK);
                            vmf.pgoff = old_page->index;
                            vmf.flags = FAULT_FLAG_WRITE|FAULT_FLAG_MKWRITE;
                            vmf.page = old_page;
                            /*
                             * Notify the address space that the page is about to
                             * become writable so that it can prohibit this or wait
                             * for the page to get into an appropriate state.
                             *
                             * We do this without the lock held, so that it can
                             * sleep if it needs to.
                             */
继承事业,薪火相传
返回列表