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

< PAGE_SIZE ; i++, j += block_size)if (!(zones[i] = bmap(swapf,block++))) {printk("rw_swap_page: bad swap file\n");return 0;}zones_used = i;dev = swapf->i_dev;} ...//在其中提交申请submit_bhbrw_page(rw, page, dev, zones, block_size);..}
4.2高速缓存
高速缓存不像普通内存换出那样在页面短缺的时候才同步,会周期性的(或者在发现dirty的bh过多时)通过去,以防止脏缓存的集中性写入 。
balance_dirty-->wakeup_bdflush-->flush_dirty_buffersbdflush-->flush_dirty_buffersflush_dirty_buffers{...bh = lru_list[BUF_DIRTY];...for (i = nr_buffers_type[BUF_DIRTY]; i-- > 0; bh = next) {next = bh->b_next_free;...//提交申请submit_bh,写缓存ll_rw_block(WRITE, 1, &bh);...}...}
另外因为内存短缺而执行,会将这些干净页面放入到中,如果遇到页面短缺程度比较大,也会在中将一些老化但是没同步的内存同步到盘上,然后释放至 。
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 (page->buffers) {...//从inactive_dirty_list移除del_page_from_inactive_dirty_list(page);...//释放bh,如果短缺(wait)严重会同步缓存/* Try to free the page buffers. */clearedbuf = try_to_free_buffers(page, wait);...if (!clearedbuf) {...else/* page->mapping && page_count(page) == 2 */ {//添加至inactive_clean_listadd_page_to_inactive_clean_list(page);cleaned_pages++;}...}}
try_to_free_buffers{...do {struct buffer_head *p = tmp;tmp = tmp->b_this_page;//检查是否写到盘上if (buffer_busy(p))goto busy_buffer_page;} while (tmp != bh);...//释放page对应的bh至unused_list,如果有足够的bh,则将其释放至slabif (p->b_dev != B_FREE) {remove_inode_queue(p);__remove_from_queues(p);} else__remove_from_free_list(p, index);__put_unused_buffer_head(p);//将bh对page的引用计数释放page->buffers = NULL;page_cache_release(page);...busy_buffer_page:if (wait) {//向盘上同步sync_page_buffers(bh, wait);/* We waited synchronously, so we can free the buffers. */if (wait > 1 && !loop) {loop = 1;goto cleaned_buffers_try_again;}}return 0;}
注:bh和page是两套系统:
1.bh在使用时,存放在中
2.主要是用于一些磁盘的管理结构,例如super,inode.等,这些结构都是内核使用的,不需要通过page去访问 。因为这个page所对应的多个block可能是不同设备中的不连续的block 。
3.相比于,更偏重于进程的访问(/),一个page和inode中连续的block是相对应的,page.index指的是page在inode中的逻辑偏移 。但是在的bh不足时,会向申请bh 。
4.在内核释放一些不需要的bh时,是通过释放,存放在中;
如果内核在执行过程中出问题,需要将之前依赖的一些bh释放时,会使用接口,将其释放至,但是还能通过hash(dev,block)找到bh;
但是可能因为一些特殊情况(例如改变文件系统的逻辑块大小),会将彻底释放的bh放到中(因为已经改变,要重新将其分配) 。因为bh已无效,hash(dev,block)是断开的;
如果要将bh释放给slab,需要通过head(一般是进程出错自己释放,或者由释放page的时候一起释放)
5.总结
是否在hash中
是否指向实际内存(page)

有内存
在(小概率不在)
有内存
不在
没内存
5.-->buddy系统
这主要是将page彻底回收(与断开),然后通过释放给buddy系统 。
kreclaimd{...//将page从address_space断开,并且将hash移除page = reclaim_page(zone);...//释放给buddy__free_page(page);...}reclaim_page{...maxscan = zone->inactive_clean_pages;while ((page_lru = zone->inactive_clean_list.prev) !=&zone->inactive_clean_list && maxscan--) {page = list_entry(page_lru, struct page, lru);...//这两个分别从swapper_space,和inode.i_mapping中移除,解除hash 。/* OK, remove the page from the caches. */if (PageSwapCache(page)) {__delete_from_swap_cache(page);goto found_page;}if (page->mapping) {__remove_inode_page(page);goto found_page;}...}...found_page://从inactive_clean_list中移除del_page_from_inactive_clean_list(page);...}