关于mapping_mapped和page_mapped

2750阅读 0评论2015-12-22 cengku
分类:LINUX

我们通常所说的page mapped是指page建立了对应的页表项,但是其实还有一种mapped是指page被映射到用户态线性地址,及我们通常所说的建立vma,这两种mapped很容易混淆,咱这来一次性把这个给理清楚。

点击(此处)折叠或打开

  1. /*
  2.  * Might pages of this file be mapped into userspace?
  3.  */
  4. static inline int mapping_mapped(struct address_space *mapping)
  5. {
  6.     return    !RB_EMPTY_ROOT(&mapping->i_mmap);
  7. }

点击(此处)折叠或打开

  1. /*
  2.  * Return true if this page is mapped into pagetables.
  3.  */
  4. static inline int page_mapped(struct page *page)
  5. {
  6.     return atomic_read(&(page)->_mapcount) >= 0;
  7. }
偶然碰到个社区有人发用page_mapped替代mapping_mapped来检测page是否真正被*mapped*的patch,于是扒了下kernel的代码和changelog,发现Lei Ming以前发的提升arm flush dcache的patch:
commit 81f28946a8b066d484ca8935ff545d94ce730aa3
Author: Ming Lei
Date:   Wed Jun 5 02:44:00 2013 +0100

    ARM: 7746/1: mm: lazy cache flushing on non-mapped pages
    
    Currently flush_dcache_page() thinks pages as non-mapped if
    mapping_mapped(mapping) return false. This approach is very
    coase:
        - mmap on part of file may cause all pages backed on
        the file being thought as mmaped
    
        - file-backed pages aren't mapped into user space actually
        if the memory mmaped on the file isn't accessed
    
    This patch uses page_mapped() to decide if the page has been
    mapped.

comment里面写得很详细了,检测page是否被mapped最好是从page本身出发,而不应该通过上层的address_space,我们知道一个文件只会用一个address_space来管理所有属于它的page,这就可能出现comment说的这种情况,file先被mmap了一段,后续被load进来的page的mapping还是指向这个address_space,页表已经建好,但是如果没有被用户态线程访问,那就不会分配对应的vma (rb-tree节点),好,那现在如果把前面的mmap解除,address_space的rb-tree会被清空,这个时候如果再通过mapping_mapped检测后面load进来的page是否mapped,则会返回false,但是实际上不是,这样在truncate或者invalidate page的时候出现遗漏。
再来看page_mapped,它是直接检测_mapcount,这个参数初始化是-1,在buddy里面的时候也是负值,一旦建立页表(mapped)的就没被设置为非负值,所有通过它来检测一个page是否建立页表才是最严谨的,或者说唯一正确的方式。
上一篇:linux percpu机制解析
下一篇:抢占式内核