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