做人呢,最紧要就系开心啦

linux源码解析15- 匿名页面的生命周期

1,051次阅读
没有评论

1. 匿名页面的产生

从内核角度看,如下情况会产生匿名页面:

1.1 用户空间 malloc()/mmap()分配的内存;

在内核发生缺页中断时,调用 do_anonymous_page()产生匿名页;

1.2 写时复制:

当缺页终端出现写保护错误时,分两种情况:

(1)调用 do_wp_page()函数分配
a. 只读的 special 映射的页,例如映射到 zero_page 的页面;
b. 多个映射的匿名页面,即 page->_mapcount>0;
c. 只读的私有映射的内容的 page cache;
d.KSM 页面;

(2)调用 do_cow_page()函数分配 的共享匿名页面(shmm);

这些写时复制,会新分配匿名页面;

(3)do_swap_page():
从 swap 分区读回数据时新分配匿名页面;

(4)迁移页面:

调用 do_anonymous_page()分配一个匿名页面初始状态:

page->_refcount=1;
page->_mapcount=0 ;
设置 PG_swapbacked 标志;加入 LRU_ACTIVE_ANON 链表,并设置 PG_lru 标志;page->mapping 指向 vma 的 av 结构;

2. 匿名页面的使用:

在缺页异常处理时,就建立了虚拟地址到 page 的映射;用户进程访问虚拟地址即访问匿名页面的内容;

3. 匿名页面的换出:

系统内存紧缺时,需要回收一些页面来释放内存;
匿名页面刚分配时加入到活跃链表 LRU_ACTIVE_ANON 头部,在活跃 LRU 链表移动一段时间后,到达活跃 LRU 尾部;

shrink_page_list()函数把该页面加入不活跃 LRU 链表 LRU_INACTIVE_ANON;

shrink_page_list(); // 活跃链表 -> 不活跃链表

第一次扫描不活跃链表

为该页面分配 swap 分区空间;

shrink_page_list()->add_to_swap()

此时匿名页状态;

page->_refcount = 3;
page->_mapcount = 0;
page->flags = PG_lru|PG_swapbacked|PG_swapcache|PG_dirty|PG_uptodate|PG_locked;

注:分离链表时_refcount++,add_to_swap()也会让_refcount++,所以这里_refcount=3;

add_to_swap()还增加若干个页面标志位;

shrink_page_list()->try_to_unmap()
通过 RMAP 去寻找所有索引映射的 VMA 和 PTE,并解除映射,运行后,匿名页状态:

page->_refcount = 2;
page->_mapcount = -1;// 没有 pte 映射,已经解除

shrink_page_list()->pageout()
把页面写回 swap 分区,page 状态

page->_refcount = 2;
page->_mapcount = -1;// 没有 pte 映射,已经解除
page->flags = PG_lru|PG_swapbacked|PG_swapcache|PG_reclaim|PG_writeback;

pageout()函数作用:

检查该页面是否可以释放;
清除 PG_dirty 标志位;
设置 PG_reclaim 标志;
调用 swap_writepage 设置 PG_writeback, 清除 PG_lock;
在向交换分区写内容时,kswapd 不会一直等该页面写完,而是将该页面放回不活跃 LRU 链表头部;

第二次扫描不活跃链表

若写 swap 还没完成,PG_writeback 标志位还在,继续放入不活跃链表头部;

写入 swap 分区已完成,Blocklayer 层回调 end_swap_bio_write()>end_page_writeback();完成如下操作:

清除 PG_writeback 标志位;
唤醒等待在该页的写回线程,wake_up_page(page,PG_writeback);

shink_page_list->__remove_mapping()

page_freeze_refs(page,2);// 判断 page->_refcount 是否为 2,并且将计数设置 0
清 PG_swapcache 标志位
清 PG_locked 标志位

此时 page 状态:

page->_refcount = 0;
page-_mapcount=-1
    page->flages =(PG_update|PG_swapbacked)

最后把 page 加入 free_page 链表中,释放该页;
因此,该匿名页面的转台是页面内容已经被写入交换分区,实际物理页面已经释放;

4. 匿名页面的换入

匿名页面换出到 swap 分区后,如果应用程序要读写这个页面,会触发缺页中断,由于 pte 不为空,且 pte->present 不在内存中;

调用 do_swap_page()函数重新读取该页面内容。

5. 匿名页面的销毁

当用户进程关闭或者退出时,扫描这个用户进程所有 vma,并清除 vma 上的所有映射,如果符合释放标准,相关页面会被释放;

下图概括匿名页的整个生命周期;

周期图.jpg

正文完
 
admin
版权声明:本站原创文章,由 admin 2022-04-20发表,共计2063字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
评论(没有评论)