Chinaunix

标题: 高端内存:永久映射方式 [打印本页]

作者: diandianlianyi    时间: 2010-11-21 01:01
标题: 高端内存:永久映射方式
pkmap_count 保留了一个数组:当对应的表项为0是,说明相应的页表项还没有用于映射,当为1时,说明相应的页表项也没有用于映射,但是不能使用,因为其对应的TLB表项还没有刷新。当大于1时,则说明已经用于某个内核成分的映射,这里我觉得有个问题,因为数组每个项的初值为0.,当第一次使用该项对应的页表项被用于映射时,kmap使得数组该项值加1,变为1,此时分明是有内核成分在使用该页表项,但是根据开始的论述,此时该页表项没有用于映射!怎么可能呢?
作者: tempname2    时间: 2010-11-21 12:35
在map_new_virtual( ) 里找到空项之后将相应数组元素值设为一,返回到kmap_high()时又将其值加1,所以有一个人使用数组相应元素值为2.

这样安排大概是为了优化对TLB的使用,即尽量延迟删除页映射(及相应TLB项).

  1. void * kmap_high(struct page * page)
  2. {
  3.     unsigned long vaddr;
  4.     spin_lock(&kmap_lock);
  5.     vaddr = (unsigned long) page_address(page);
  6.     if (!vaddr)
  7.         vaddr = map_new_virtual(page);
  8.     pkmap_count[(vaddr-PKMAP_BASE) >> PAGE_SHIFT]++;
  9.     spin_unlock(&kmap_lock);
  10.     return (void *) vaddr;
  11. }

复制代码
if ( !vaddr)只会在第一次映射该page frame时进去.一旦进去了,map_new_virtual会将其在pkmap_count中的对应项设为1,并将映射关系写进hashtable.返回又将对应数组项加1.所以有一个人使用,pkmap_count里的对应值就为2.

如果第二次又有人映射这个page frame,由于page_address可以在hashtable找到映射关系,vaddr是有效值,不会进入if ,pkmap_count里对应项值再加1.

删除映射的时候,仅仅将pkmap_count里对应项值减一.假设只有一个人使用之,本来可以马上解除映射并flush tlb,但这里尽量延迟做这件事.pkmap_count里为1的项都是这种情况.这时,映射依然有效,hashtable中依然有其映射记录,tlb中依然有其映射缓存.映射其它page frame时会跳过这些地址.这样做就是期待同样的page frame再一次被映射,由于hashtable中的记录未被删除,同样的page frame再度被映射时还是会跳过那个if (虽然从逻辑上来看映射已经被解除了),tlb中的项还可以继续用,这就达到了优化作用.

但不可能一直这样等待,总会发生虚拟地址用完的情况,这时就放弃等待,扫描整个pkmap_count,把其中值为1的项置0,删除hasntable中的记录,flush对应的tlb项,此时才算是真正解除了映射.所以,形式上解除映射的kunmap_high还有一个任务是看有没有进程在等待使用虚拟地址,有的话就将其唤醒.当然它们还是会先从pkmap_count中值为0的项开始找起,但最终会发现无可用项,于是调用flush_all_zero_pkmaps( )清除那些pkmap_count值为1的项.
作者: diandianlianyi    时间: 2010-11-21 15:36
回复 2# tempname2


    Orz,谢谢!




欢迎光临 Chinaunix (http://bbs.chinaunix.net/) Powered by Discuz! X3.2