第6节 交换机制

6.6.1 交换的基本原理 


 如前所述,每个进程的可以使用的虚存空间很大(3GB),但实际使用的空间并不大,一般不会超过几MB,大多数情况下只有几十K或几百K。可是,当系统的进程数达到几百甚至上千个时,对存储空间的总需求就很大,在这种情况下,一般的物理内存量就很难满足要求。因此,在计算机技术的发展史上很早就有了把内存的内容与一个专用的磁盘空间交换的技术,在Linux中,我们把用作交换的磁盘空间叫做交换文件或交换区。 


 交换技术已经使用了很多年。第一个Unix系统内核就监控空闲内存的数量。当空闲内存数量小于一个固定的极限值时,就执行换出操作。换出操作包括把进程的整个地址空间拷贝到磁盘上。反之,当调度算法选择出一个进程运行时,整个进程又被从磁盘中交换进来 


 现代的Unix(包括Linux)内核已经摒弃了这种方法,主要是因为当进行换入换出时,上下文切换的代价相当高。在Linux中,交换的单位是页面而不是进程。尽管交换的单位是页面,但交换还是要付出一定的代价,尤其是时间的代价。实际上,在操作系统中,时间和空间是一对矛盾,常常需要在二者之间作出平衡,有时需要以空间换时间,有时需要以时间换空间,页面交换就是典型的以时间换空间。这里要说明的是,页面交换是不得已而为之,例如在时间要求比较紧急的实时系统中,是不宜采用页面交换机制的,因为它使程序的执行在时间上有了较大的不确定性。因此,Linux给用户提供了一种选择,可以通过命令或系统调用开启或关闭交换机制。 


 在页面交换中,页面置换算法是影响交换性能的关键性指标,其复杂性主要与换出有关。具体说来,必须考虑四个主要问题: 


 · 哪种页面要换出 
 · 如何在交换区中存放页面 
 · 如何选择被交换出的页面 
 · 何时执行页面换出操作 


 请注意,我们在这里所提到的页或页面指的是其中存放的数据,因此,所谓页面的换入换出实际上是指页面中数据的换入换出。 


1.哪种页面被换出 


 实际上,交换的最终目的是页面的回收。并非内存中的所有页面都是可以交换出去的。事实上,只有与用户空间建立了映射关系的物理页面才会被换出去,而内核空间中内核所占的页面则常驻内存。我们下面对用户空间中的页面和内核空间中的页面给出进一步的分类讨论。 


 可以把用户空间中的页面按其内容和性质分为以下几种: 


 (1) 进程映像所占的页面,包括进程的代码段、数据段、堆栈段以及动态分配的“存储堆”(参见图6.13)。 


 (2) 通过系统调用mmap()把文件的内容映射到用户空间 


 (3) 进程间共享内存区 


 对于第1种情况,进程的代码段数据段所占的内存页面可以被换入换出,但堆栈所占的页面一般不被换出,因为这样可以简化内核的设计。 


 对于第2种情况,这些页面所使用的交换区就是被映射的文件本身。 


 对于第3种情况,其页面的换入换出比较复杂。 


 与此相对照,映射到内核空间中的页面都不会被换出。具体来说,内核代码和内核中的全局量所占的内存页面既不需要分配(启动时被装入),也不会被释放,这部分空间是静态的。(相比之下,进程的代码段和全局量都在用户空间,所占的内存页面都是动态的,使用前要经过分配,最后都会被释放,中途可能被换出而回收后另行分配) 


 除此之外,内核在执行过程中使用的页面要经过动态分配,但永驻内存,此类页面根据其内容和性质可以分为两类: 


 (1) 内核调用kmalloc()或vmalloc()为内核中临时使用的数据结构而分配的页于是立即释放。但是,由于一个页面中存放有多个同种类型的数据结构,所以要到整个页面都空闲时才把该页面释放。 


 (2) 内核中通过调用alloc_pages(),为某些临时使用和管理目的而分配的页面,例如,每个进程的内核栈所占的两个页面、从内核空间复制参数时所使用的页面等等。这些页面也是一旦使用完毕便无保存价值,所以立即释放。 


 在内核中还有一种页面,虽然使用完毕,但其内容仍有保存价值,因此,并不立即释放。这类页面“释放”之后进入一个LRU队列,经过一段时间的缓冲让其“老化”。如果在此期间又要用到其内容了,就又将其投入使用,否则便继续让其老化,直到条件不再允许时才加以回收。这种用途的内核页面大致有以下这些: 


 · 文件系统中用来缓冲存储一些文件目录结构dentry的空间 
 · 文件系统中用来缓冲存储一些索引节点inode的空间 
 · 用于文件系统读/写操作的缓冲区 


2.如何在交换区中存放页面 


 我们知道物理内存被划分为若干页面,每个页面的大小为4KB。实际上,交换区也被划分为块,每个块的大小正好等于一页,我们把交换区中的一块叫做一个页插槽(page slot),意思是说,把一个物理页面插入到一个插槽中。当进行换出时,内核尽可能把换出的页放在相邻的插槽中,从而减少在访问交换区时磁盘的寻道时间。这是高效的页面置换算法的物质基础。 


 如果系统使用了多个交换区,事情就变得更加复杂了。快速交换区(也就是存放在快速磁盘中的交换区)可以获得比较高的优先级。当查找一个空闲插槽时,要从优先级最高的交换区中开始搜索。如果优先级最高的交换区不止一个,为了避免超负荷地使用其中一个,应该循环选择相同优先级的交换区。如果在优先级最高的交换区中没有找到空闲插槽,就在优先级次高的交换区中继续进行搜索,依此类推。 


3.如何选择被交换出的页面 


 页面交换是非常复杂的,其主要内容之一就是如何选择要换出的页面,我们以循序渐进的方式来讨论页面交换策略的选择。 


 策略一,需要时才交换。每当缺页异常发生时,就给它分配一个物理页面。如果发现没有空闲的页面可供分配,就设法将一个或多个内存页面换出到磁盘上,从而腾出一些内存页面来。这种交换策略确实简单,但有一个明显的缺点,这是一种被动的交换策略,需要时才交换,系统势必要付出相当多的时间进行换入换出。 


 策略二,系统空闲时交换。与策略一相比较,这是一种积极的交换策略,也就是,在系统空闲时,预先换出一些页面而腾出一些内存页面,从而在内存中维持一定的空闲页面供应量,使得在缺页中断发生时总有空闲页面可供使用。至于换出页面的选择,一般都采用LRU(最近最少使用)算法。但是这种策略实施起来也有困难,因为并没有哪种方法能准确地预测对页面的访问,所以,完全可能发生这样的情况,即一个好久没有受到访问的页面刚刚被换出去,却又要访问它了,于是又把它换进来。在最坏的情况下,有可能整个系统的处理能力都被这样的换入/换出所影响,而根本不能进行有效的计算和操作。这种现象被称为页面的“抖动”。 


 策略三,换出但并不立即释放。当系统挑选出若干页面进行换出时,将相应的页面写入磁盘交换区中,并修改相应页表中页表项的内容(把present标志位置为0),但是并不立即释放,而是将其page结构留在一个缓冲(cache)队列中,使其从活跃(active)状态转为不活跃(Inactive)状态。至于这些页面的最后释放,要推迟到必要时才进行。这样,如果一个页面在释放后又立即受到访问,就可以从物理页面的缓冲队列中找到相应的页面,再次为之建立映射。由于此页面尚未释放,还保留着原来的内容,就不需要磁盘读入了。经过一段时间以后,一个不活跃的内存页面一直没有受到访问,那这个页面就需要真正被释放了。 


 策略四,把页面换出推迟到不能再推迟为止。实际上,策略三还有值得改进的地方。首先在换出页面时不一定要把它的内容写入磁盘。如果一个页面自从最近一次换入后并没有被写过(如代码),那么这个页面是“干净的”,就没有必要把它写入磁盘。其次,即使“脏”页面,也没有必要立即写出去,可以采用策略三。至于“干净”页面,可以一直缓冲到必要时才加以回收,因为回收一个“干净”页面花费的代价很小。 


 下面对物理页面的换入换出给出一个概要描述,这里涉及到前面介绍的page结构和free_area结构: 


 · 释放页面。如果一个页面变为空闲可用,就把该页面的page结构链入某个页面管理区(zone)的空闲队列free_area,同时页面的使用计数count减1。 
 · 分配页面。调用__alloc_pages()或__get_free_page()从某个空闲队列分配内存页面,并将其页面的使用计数count置为1。 
 · 活跃状态。已分配的页面处于活跃状态,该页面的数据结构page通过其队列头结构lru链入活跃页面队列active_list,并且在进程地址空间中至少有一个页与该页面之间建立了映射关系。 
 · 不活跃“脏”状态。处于该状态的页面其page结构通过其队列头结构lru链入不活跃“脏”页面队列inactive_dirty_list,并且原则是任何进程的页面表项不再指向该页面,也就是说,断开页面的映射,同时把页面的使用计数count减1。 
 · 将不活跃“脏”页面的内容写入交换区,并将该页面的page结构从不活跃“脏”页面队列inactive_dirty_list转移到不活跃“干净”页面队列,准备被回收。 
 · 不活跃“干净”状态。页面page结构通过其队列头结构lru链入某个不活跃“干净”页面队列,每个页面管理区都有个不活跃“干净”页面队列inactive_clean_list。 
 · 如果在转入不活跃状态以后的一段时间内,页面又受到访问,则又转入活跃状态并恢复映射。 
 · 当需要时,就从“干净”页面队列中回收页面,也就是说或者把页面链入到空闲队列,或者直接进行分配。 


 以上是页面换入/换出及回收的基本思想,实际的实现代码还要更复杂一些。 


4.何时执行页面换出操作 


 为了避免在CPU忙碌的时候,也就是在缺页异常发生时,临时搜索可供换出的内存页面并加以换出,Linux内核定期地检查系统内的空闲页面数是否小于预定义的极限,一旦发现空闲页面数太少,就预先将若干页面换出,以减轻缺页异常发生时系统所承受的负担。当然,由于无法确切地预测页面的使用,即使这样做了也还可能出现缺页异常发生时内存依然没有足够的空闲页面。但是,预换出毕竟能减少空闲页面不够用的概率。并且通过选择适当的参数(如每隔多久换出一次,每次换出多少页),可以使临时寻找要换出页面的情况很少发生。为此,Linux内核设置了一个专伺定期将页面换出的守护进程kswapd。 


6.6.2页面交换守护进程kswapd 


 从原理上说,kswapd相当于一个进程,它有自己的进程控制块task_struct结构。与其它进程一样受内核的调度。而正因为内核将它按进程来调度,就可以让它在系统相对空闲的时候来运行。不过,与普通进程相比,kswapd有其特殊性。首先,它没有自己独立的地址空间,所以在近代操作系统理论中把它称为“线程”以与进程相区别。那么,kswapd的地址空间是什么?实际上,内核空间就是它的地址空间。在这一点上,它与中断服务例程相似。其次,它的代码是静态地链接在内核中的,因此,可以直接调用内核中的各种子程序和函数。 


 Kswapd的源代码基本上都在mm/vmscan.c中,图6.18给出了kswapd中与交换有关的主要函数调用关系。 






图 6.18 kswapd 的实现代码中与交换相关的主要函数的调用关系 


从上面的调用关系可以看出, kswapd的实现相当复杂,这不仅仅涉及复杂的页面交换技术,还涉及与磁盘相关的具体文件操作,因此,为了理清思路,搞清主要内容,我们对一些主要函数给予描述: 


1.Kswapd() 


 在Linux2.4.10以后的版本中对kswapd()的实现代码进行了模块化组织,可读性大大加强,代码如下: 
int kswapd(void *unused) 
 { 
 struct task_struct *tsk = current; 
 DECLARE_WAITQUEUE(wait, tsk); 
 daemonize(); /*内核线程的初始化*/ 
 strcpy(tsk->comm, "kswapd"); 
 sigfillset(&tsk->blocked); /*把进程PCB中的阻塞标志位全部置为1*/ 
 /* 
 * Tell the memory management that we're a "memory allocator", 
 * and that if we need more memory we should get access to it 
 * regardless (see "__alloc_pages()"). "kswapd" should 
 * never get caught in the normal page freeing logic. 
 * 
 * (Kswapd normally doesn't need memory anyway, but sometimes 
 * you need a small amount of memory in order to be able to 
 * page out something else, and this flag essentially protects 
 * us from recursively trying to free more memory as we're 
 * trying to free the first piece of memory in the first place). 
 */ 
 tsk->flags |= PF_MEMALLOC; /*这个标志表示给kswapd要留一定的内存*/ 
 /* 
 * Kswapd main loop. 
 */ 
 for (;;) { 
 __et_current_state(TASK_INTERRUPTIBLE); 
 add_wait_queue(&kswapd_wait, &wait); /*把kswapd 加入等待队列*/ 
 mb(); /*增加一条汇编指令*/ 
 if (kswapd_can_sleep()) /*检查调度标志是否置位*/ 
 schedule(); /*调用调度程序*/ 
 set_current_state(TASK_RUNNING); /*让kswapd 处于就绪状态*/ 
 remove_wait_queue(&kswapd_wait, &wait); /*把kswapd 从等待队列删除*/ 
 /* 
 * If we actually get into a low-memory situation, 
 * the processes needing more memory will wake us 
 * up on a more timely basis. 
 */ 
 kswapd_balance(); /* kswapd 的核心函数,请看后面内容*/ 
 run_task_queue(&tq_disk); /*运行tq_disk 队列中的例程*/ 
 } 
 } 
 kswapd内核线程的创建如下: 
 static int __init kswapd_init(void) 
 { 
 printk("Starting kswapd\n"); 
 swap_setup(); 
 kernel_thread(kswapd, NULL, CLONE_FS | CLONE_FILES | CLONE_SIGNAL); 
 return 0; 
 } 






函数kswapd_init()是在系统初始化期间被调用的。它主要做两件事,其中swap_setup()根据物理内存的大小设定一个全局变量page_cluster。这是一个与磁盘设备驱动有关的参数。由于读磁盘时先要经过寻道,而寻道是比较费时的操作,因此,为了节省时间,每次最好多读几个页面,这叫“预读”。到底每次预读几个页面,就是由这个函数根据内存本身的大小给出的(为2,3或4)。另外一个主要的任务就是调用kernel_thread()创建内核线程kswapd。 


 从上面的介绍可以看出,kswapd成为内核的一个线程,其主循环是一个无限循环。循环一开始,把它加入等待队列,但如果调度标志为1,就执行调度程序,紧接着就又把它从等待队列删除,将其状态变为就绪。只要调度程序再次执行,它就会得到执行,如此周而复始进行下去。 


2.kswapd_balance()函数 


 从该函数的名字可以看出,这是一个要求得平衡的函数,那么,求得什么样的平衡呢?在本章的初始化一节中,我们介绍了物理内存的三个层次,即存储节点、管理区和页面。所谓平衡就是对页面的释放要均衡地在各个存储节点、管理区中进行,代码如下: 
static void kswapd_balance(void) 
 { 
 int need_more_balance; 
 pg_data_t * pgdat; 
 do { 
 need_more_balance = 0; 
 pgdat = pgdat_list; 
 do 
 need_more_balance |= kswapd_balance_pgdat(pgdat); 
 while ((pgdat = pgdat->node_next)); 
 } while (need_more_balance); 
 } 






这个函数比较简单,主要是对每个存储节点进行扫描。然后又调用kswapd_balance_pgdat()对每个管理区进行扫描:
static int kswapd_balance_pgdat(pg_data_t * pgdat) 
 {
 int need_more_balance = 0, i; 
 zone_t * zone; 
 for (i = pgdat->nr_zones-1; i >= 0; i--) { 
 zone = pgdat->node_zones + i; 
 if (unlikely(current->need_resched)) 
 schedule(); 
 if (!zone->need_balance) 
 continue; 
 if (!try_to_free_pages(zone, GFP_KSWAPD, 0)) { 
 zone->need_balance = 0; 
 __set_current_state(TASK_INTERRUPTIBLE); 
 schedule_timeout(HZ); 
 continue; 
 } 
 if (check_classzone_need_balance(zone)) 
 need_more_balance = 1; 
 else 
 zone->need_balance = 0; 
 } 






其中,最主要的函数是try_to_free_pages(),能否调用这个函数取决于平衡标志need_balance是否为1,也就是说看某个管理区的空闲页面数是否小于最高警戒线,这是由check_classzone_need_balance()函数决定的。当某个管理区的空闲页面数小于其最高警戒线时就调用try_to_free_pages()。 


3.try_to_free_pages() 


 该函数代码如下: 
int try_to_free_pages(zone_t *classzone, unsigned int gfp_mask, unsigned int order) 
 { 
 int priority = DEF_PRIORITY; 
 int nr_pages = SWAP_CLUSTER_MAX; 
 gfp_mask = pf_gfp_mask(gfp_mask); 
 do { 
 nr_pages = shrink_caches(classzone, priority, gfp_mask, nr_pages); 
 if (nr_pages <= 0) 
 return 1; 
 } while (--priority); 
 /* 
 * Hmm.. Cache shrink failed - time to kill something? 
 * Mhwahahhaha! This is the part I really like. Giggle. 
 */ 
 out_of_memory(); 
 return 0; 
 } 






其中的优先级表示对队列进行扫描的长度,缺省的优先级DEF_PRIORITY为6(最低优先级)。假定队列长度为L,优先级6就表示要扫描的队列长度为L/26,所以这个循环至少循环6次。nr_pages为要换出的页面数,其最大值SWAP_CLUSTER_MAX为32。其中主要调用的函数为shrink_caches(): 
static int shrink_caches(zone_t * classzone, int priority, unsigned int gfp_mask, int nr_pages) 
 { 
 int chunk_size = nr_pages; 
 unsigned long ratio; 
 nr_pages -= kmem_cache_reap(gfp_mask); 
 if (nr_pages <= 0) 
 return 0; 
 nr_pages = chunk_size; 
 /* try to keep the active list 2/3 of the size of the cache */ 
 ratio = (unsigned long) nr_pages * nr_active_pages / ((nr_inactive_pages + 1) * 2); 
 refill_inactive(ratio); 
 nr_pages = shrink_cache(nr_pages, classzone, gfp_mask, priority); 
 if (nr_pages <= 0) 
 return 0; 
 shrink_dcache_memory(priority, gfp_mask); 
 shrink_icache_memory(priority, gfp_mask); 
 1 #ifdef CONFIG_QUOTA 
 shrink_dqcache_memory(DEF_PRIORITY, gfp_mask); 
 #endif 
 return nr_pages; 
 } 






其中kmem_cache_reap()函数“收割(reap)”由Slab机制管理的空闲页面。如果从Slap回收的页面数已经达到要换出的页面数nr_pages,就不用从其它地方进行换出。refill_inactive()函数把活跃队列中的页面移到非活跃队列。shrink_cache()函数把一个“洗净”且未加锁的页面移到非活跃队列,以便该页能被尽快释放。 


 此外,除了从各个进程的用户空间所映射的物理页面中回收页面外,还调用shrink_dcache_memory()、shrink_icache_memory()及shrink_dqcache_memory()回收内核数据结构所占用的空间。在文件系统一章将会看到,在打开文件的过程中,要分配和使用代表着目录项的dentry数据结构,还有代表着文件索引节点inode的数据结构。这些数据结构在文件关闭后并不立即释放,而是放在LRU队列中作为后备,以防在不久将来的文件操作中又用到。这样经过一段时间后,就有可能积累起大量的dentry数据结构和inode数据结构,从而占用数量可观的物理页面。这时,就要通过这些函数适当加以回收。 


4.页面置换 


 到底哪些页面会被作为后选页以备换出,这是由Swap_out()和shrink_cache()一起完成的。这个过程比较复杂,这里我们抛开源代码,以理清思路为目标。 


 shrink_cache()要做很多换出的准备工作。它关注两个队列:“活跃的” LRU 队列 和 “非活跃的” FIFO 队列,每个队列都是struct page形成的链表。该函数的代码比较长,我们把它所做的工作概述如下: 


 · 把引用过的页面从活跃队列的队尾移到该队列的队头(实现LRU策略)。 
 · 把未引用过的页面从活跃队列的队尾移到非活跃队列的队头(为准备换出而排队)。 
 · 把脏页面安排在非活跃队列的队尾准备写到磁盘。 
 · 从非活跃队列的队尾恢复干净页面(写出的页面就成为干净的) 


6.6.3交换空间的数据结构 


 Linux支持多个交换文件或设备,它们将被swapon 和 swapoff 系统调用来打开或关闭。每个交换文件或设备都可用swap_info_struct 结构来描述: 


 struct swap_info_struct { 


 unsigned int flags; 


 kdev_t swap_device; 


 spinlock_t sdev_lock; 


 struct dentry * swap_file; 


 struct vfsmount *swap_vfsmnt; 


 unsigned short * swap_map; 


 unsigned int lowest_bit; 


 unsigned int highest_bit; 


 unsigned int cluster_next; 


 unsigned int cluster_nr; 


 int prio; /* swap priority */ 


 int pages; 


 unsigned long max; 


 int next; /* next entry on swap list */ 


 }; 


 extern int nr_swap_pages; 


 flags域(SWP_USED 或SWP_WRITEOK)用作控制访问交换文件。当swapoff被调用(为了取消一个文件)时,SWP_WRITEOK置成 off,使在文件中无法分配空间。如果swapon加入一个新的交换文件时,SWP_USED 被置位。这里还有一静态变量(nr_swapfiles)来记录当前活动的交换文件数。 
 域lowest_bit ,highest_bit表明在交换文件中空闲范围的边界,这是为了快速寻址。 


 当用户程序mkswap初始化交换文件或设备时,在文件的第一个页插槽的前10个字节,有一个包含有位图的标志,在位图里初始化为0,代表坏的页插槽,1代表相关页插槽是空闲的。 


 当用户程序调用swapon()时,有一页被分配给swap_map。 


 swap_map为在交换文件中每一个页插槽保留了一个字节,0代表可用页插槽,128代表不可用页插槽。它被用于记下交换文件中每一页插槽上的swap请求。 


 内存中的一页被换出时,调用get_swap_page()会得到一个一个记录换出位置的索引,然后在页表项中回填(1--31位)此索引。这是为了在发生在缺页异常时进行处理(do_no_page)。索引的高7位给定交换文件,后24位给定设备中的页插槽号。 


 另外函数swap_duplicate()被copy_page_tables()调用来实现子进程在fork()时继承被换出的页面,这里要增加域swap_map中此页面的count值,任何进程访问此页面时,会换入它的独立的拷贝。 


 swap_free()减少域swap_map中的count值,如果count减到0时,则这页面又可再次分配(get_swap_page),在把一个换出页面调入(swap_in)内存时或放弃一个页面时(free_one_table) 调用swap_free()。 


 相关函数在文件filemap.c中 


6.6.4交换空间的应用 


1. 建立交换空间 


 作为交换空间的交换文件实际就是通常的文件,但文件的扇区必须是连续的,也即,文件中必须没有“洞”,另外,交换文件必须保存在本地硬盘上。 


 由于内核要利用交换空间进行快速的内存页面交换,因此,它不进行任何文件扇区的检查,而认为扇区是连续的。由于这一原因,交换文件不能包含洞。可用下面的命令建立无洞的交换文件: 


 $ dd if=/dev/zero of=/extra-swap bs=1024 count=2048 


 2048+0 records in 


 2048+0 records out 


 上面的命令建立了一个名称为 extra-swap,大小为 2048K 字节的交换文件。对 i386 系统而言,由于其页面尺寸为 4K,因此最好建立一个大小为 4K 倍数的交换文件;对 Alpha AXP 系统而言,最好建立大小为 8K 倍数的交换文件。 


 交换分区和其他分区也没有什么不同,可象建立其他分区一样建立交换分区。但该分区不包含任何文件系统。分区类型对内核来讲并不重要,但最好设置为 Linux Swap 类型(即类型 82)。 


 建立交换文件或交换分区之后,需要在文件或分区的开头写入签名,写入的签名实际是由内核使用的一些管理信息。写入签名的命令为 mkswap,如下所示: 


 $ mkswap /extra-swp 2048 


 Setting up swapspace, size = 2088960 bytes 


 $ 


 这时,新建立的交换空间尚未开始使用。使用 mkswap 命令时必须小心,因为该命令不会检查文件或分区内容,因此极有可能覆盖有用的信息,或破坏分区上的有效文件系统信息。 


 Linux 内存管理子系统将每个交换空间的大小限制在 127M (实际为 (4096.10)*8*4096 = 133890048 Byte = 127.6875Mb)。可以在系统中同时使用 16 个交换空间,从而使交换空间总量达到 2GB。 


2. 使用交换空间 


 利用 swapon 命令可将经过初始化的交换空间投入使用。如下所示: 


 $ swapon /extra-swap 


 $ 


 如果在 /etc/fstab 文件中列出交换空间,则可自动将交换空间投入使用: 


 /dev/hda5 none swap sw 0 0 


 /extra-swap none swap sw 0 0 


 实际上,启动脚本会运行 swapon –a 命令,从而将所有出现在 /etc/fstab 文件中的交换空间投入使用。 


 利用 free 命令,可查看交换空间的使用。如下所示: 


 $ free 


 total used free shared buffers 


 Mem: 15152 14896 256 12404 2528 


 -/+ buffers: 12368 2784 


 Swap: 32452 6684 25768 


 $ 


 该命令输出的第一行(Mem: ) 显示了系统中物理内存的使用情况。total 列显示的是系统中的物理内存总量;used 列显示正在使用的内存数量;free 列显示空闲的内存量;shared 列显示由多个进程共享的内存量,该内存量越多越好;buffers 显示了当前的缓冲区高速缓存的大小。 


 输出的最后一行 (Swap: ) 显示了有关交换空间的类似信息。如果该行的内容均为 0,表明当前没有活动的交换空间。 


 利用top 命令或查看 /proc 文件系统中的 /proc/meminfo 文件可获得相同的信息。 


 利用 swapoff 命令可移去使用中的交换空间。但该命令应只用于临时交换空间,否则有可能造成系统崩溃。 


 swapoff –a 命令按照 /etc/fstab 文件中的内容移去所有的交换空间,但任何手工投入使用的交换空间保留不变。 


3. 分配交换空间 


 大多数人认为,交换空间的总量应该是系统物理内存量的两倍,实际上这一规则是不正确的,正确的交换空间大小应按如下规则确定: 


 · 估计需要的内存总量。运行想同时运行的所有程序,并利用 free 或 ps 程序估计所需的内存总量,只需大概估计。 
 · 增加一些安全性余量。 
 · 减去已有的物理内存数量,然后将所得数据取整为 MB,这就是应当的交换空间大小。 
 · 如果得到的交换空间大小远远大于物理内存量,则说明需要增加物理内存数量,否则系统性能会因为过分的页面交换而下降。 


 当计算的结果说明不需要任何交换空间时,也有必要使用交换空间。Linux 从性能的角度出发,会在磁盘空闲时将某些页面交换到交换空间中,以便减少必要时的交换时间。另外,如果在不同的磁盘上建立多个交换空间,有可能提高页面交换的速度,这是因为某些硬盘驱动器可同时在不同的磁盘上进行读写操作。 

源地址:http://www.eefocus.com/article/09-06/75170s.html






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值