内存换出和缓冲区释放( 三 )


文章插图
将如下的结构写入到pte中,因为位是0,所以之后再访问该page的时候,会产生页面中断,执行,然后去hash表或者从交换盘中读取page到内存中 。
(注:swap具体函数清参考和 。这里记录一些变量含义:
type表示交换盘的编号;
表示page在交换盘中的偏移;
[type].[]表示盘上页面的计数;
.head指向的是按照prior排列的链表,
[type].next指向这个链表的下一个,
.next指向下一个分配时应该选择的 。)
3.2缓冲区
缓冲区在中将page.age递减置0的时候,会立即将其放入
refill_inactive-->refill_inactive_scanrefill_inactive_scan{if (PageTestandClearReferenced(page)) {age_page_up_nolock(page);page_active = 1;} else {age_page_down_ageonly(page);//在alloc_page中的rmqueue中,从buddy系统中获取page时,已经将page.count置1,如果只有单个进程MMU的引用或者只有buffer_head的引用,page.count为2;如果是单个进程mmap,那么这个page既被映射到MMU中,又被加载到bh中,所以page.count为3.//这里只是单独处理缓冲区的部分,处理MMU引用在try_to_swap_out 。所以如果存在page->buffers,说明其被bh引用,page.count最大是2,才能释放到inactive_dirty_list 。if (page->age == 0 && page_count(page) <=(page->buffers ? 2 : 1)) {//将page加入到inactive_dirty_list中deactivate_page_nolock(page);page_active = 0;} else {page_active = 1;}....}
4.-->
-->,主要涉及到函数,以及其调用的两个函数和,其主要是用来识别哪些page是进程长期不使用的,可以将这些page腾出来,在内存短缺的时候供其他进程使用 。
所以当内存短缺的时候,需要执行,将中不干净的页面洗净(同步到盘上),将其转入,待进一步的回收 。
4.1普通内存
普通内存在因为已经,所以在会检查page这个标志位是否置上,如果置上再将其写入到盘上
page_launder{...//遍历整个inactive_dirty_listlist,注意这里如果不移到其他管理链表中,还在inactive_dirty_list中时,会将其插入到最后maxscan = nr_inactive_dirty_pages;while ((page_lru = inactive_dirty_list.prev) != &inactive_dirty_list &&maxscan-- > 0) {page = list_entry(page_lru, struct page, lru);...if (PageDirty(page)) {int (*writepage)(struct page *) = page->mapping->a_ops->writepage;int result;if (!writepage)goto page_active;//在第二次进来的时候再向盘上写/* First time through? Move it to the back of the list */if (!launder_loop) {list_del(page_lru);list_add(page_lru, &inactive_dirty_list);UnlockPage(page);continue;}/* OK, do a physical asynchronous write to swap.*/ClearPageDirty(page);page_cache_get(page);spin_unlock(&pagemap_lru_lock);//page->mapping->a_ops->writepage,如果是交换盘是swap_writepage,如果是mmap,则是ext2_writepageresult = writepage(page);page_cache_release(page);/* And re-start the thing.. */spin_lock(&pagemap_lru_lock);//写完,在这里退出此次page的操作if (result != 1)continue;/* writepage refused to do anything */set_page_dirty(page);goto page_active;}...else if (page->mapping && !PageDirty(page)) {/** If a page had an extra reference in* deactivate_page(), we will find it here.* Now the page is really freeable, so we* move it to the inactive_clean list.*///从inactive_dirty_list移到inactive_clean_listdel_page_from_inactive_dirty_list(page);add_page_to_inactive_clean_list(page);UnlockPage(page);cleaned_pages++;} ...}
swap_writepage-->rw_swap_page-->rw_swap_page_baserw_swap_page_base{...//从swap_info中获取要写的设备(dev)或者inode(swapf)get_swaphandle_info(entry, &offset, &dev, &swapf);//获取底层的参数dev block(物理)if (dev) {zones[0] = offset;zones_used = 1;block_size = PAGE_SIZE;} else if (swapf) {int i, j;unsigned int block = offset<< (PAGE_SHIFT - swapf->i_sb->s_blocksize_bits);block_size = swapf->i_sb->s_blocksize;for (i=0, j=0; j