换出页标识符
32位系统用一个32位的整数来标识一个页面,其中type表示交换区编号,索引表示交换区中页槽的索引值。这样就可唯一标识该换出页的位置

页面回收 交换分区(二)-LMLPHP

交换缓冲区
在交换缓冲区中swapper_space,各个页面就是按照这个标识符来被组织管理起来的


  1. #ifdef CONFIG_SWAP
  2.         /*
  3.          * Anonymous process memory has backing store?
  4.          * Try to allocate it some swap space here.
  5.          */
  6.         if (PageAnon(page) && !PageSwapCache(page))
  7.             if (!add_to_swap(page, GFP_ATOMIC))
  8.                 goto activate_locked;
  9. #endif /* CONFIG_SWAP */
在shrink_page_list函数中,有上面的处理,判断如果页面属于匿名页面,就会调用add_to_swap位page在交换分区中分配一个页槽,并将这个页面加入到页面交换缓冲区。所以add_to_swap总共完成了两个动作,一个动作就是为一个page申请一个交换分区的页槽,一个动作是将页加入到页面交换缓冲区swapper_space
页面回收 交换分区(二)-LMLPHP
分配页槽的策略
get_swap_page函数会优先分配优先级高的交换分区中空闲的页槽,同优先级之间的交换分区会轮流分配空闲页槽。
大家可以想一下为什么采用这样的一种策略,优先使用高优先级的交换分区是因为高优先级的交换分区一般磁盘读写速度都比较快,优先使用加快页面换出换入的速度,同优先级的交换分区轮流分配页槽的目的是,不同的交换分区可能位于不同的磁盘上,轮流使用可以加大并行IO的可能,也是加快换入换出的速度。

scan_swap_map函数负责在具体的交换分区中查找空闲的页槽,其搜索方法也值得分析
交换系统有时候会集中在一个比较短的时间换出大量页面,这些页面也有可能是连续的,尽量把这些页面存储到一个连续的磁盘设备上,可以让页面从磁盘上换入时磁道寻址时间更加短一点。所以scan_swap_map使用了一种算法,首先在交换分区中寻找SWAPFILE_CLUSTER个空闲页槽的一块区域,然后从这个区域中一次分配空闲页槽,等这个区域分配完毕了,再次寻找一个SWAPFILE_CLUSTER空闲槽位的连续区域供给分配。


将页面加入到交换缓冲区中

  1. if (!error) {
  2.         write_lock_irq(&swapper_space.tree_lock);
  3.         error = radix_tree_insert(&swapper_space.page_tree,
  4.                         entry.val, page);
  5.         if (!error) {
  6.             page_cache_get(page);
  7.             SetPageLocked(page);
  8.             SetPageSwapCache(page);
  9.             set_page_private(page, entry.val);
  10.             total_swapcache_pages++;
  11.             __inc_zone_page_state(page, NR_FILE_PAGES);
  12.         }
  13.         write_unlock_irq(&swapper_space.tree_lock);
  14.         radix_tree_preload_end();
  15.     }

01-04 03:43