内存是Linux内核所管理的最重要的资源之一。内存管理系统是 *** 作系统中最为重要的部分,因为系统的物理内存总是少于系统所需要的内存数量。虚拟内存就是为了克服这个矛盾而采用的策略。系统的虚拟内存通过在各个进程之间共享内存而使系统看起来有多于实际内存的内存容量。Linux支持虚拟内存, 就是使用磁盘作为RAM的扩展,使可用内存相应地有效扩大。核心把当前不用的内存块存到硬盘,腾出内存给其他目的。当原来的内容又要使用时,再读回内存。以下就是我为大家整理到的详细LINUX系统内存管理的知识,欢迎大家阅读!!!
LINUX系统教程:内存管理的知识详解
一、内存使用情况监测
(1)实时监控内存使用情况
在命令行使用“Free”命令可以监控内存使用情况
代码如下:
#free
total used free shared buffers cached
Mem: 256024 192284 63740 0 10676 101004
-/+ buffers/cache: 80604 175420
Swap: 522072 0 522072
上面给出了一个256兆的RAM和512兆交换空间的系统情况。第三行输出(Mem:)显示物理内存。total列不显示核心使用的物理内存(通常大约1MB)。used列显示被使用的内存总额(第二行不计缓冲)。 free列显示全部没使用的内存。Shared列显示多个进程共享的内存总额。Buffers列显示磁盘缓存的当前大小。第五行(Swap:)对对换空间,显示的信息类似上面。如果这行为全0,那么没使用对换空间。在缺省的状态下,free命令以千字节(也就是1024字节为单位)来显示内存使用情况。可以使用—h参数以字节为单位显示内存使用情况,或者可以使用—m参数以兆字节为单位显示内存使用情况。还可以通过—s参数使用命令来不间断地监视内存使用情况:
#free –b –s2
这个命令将会在终端窗口中连续不断地报告内存的使用情况,每2秒钟更新一次。
(2)组合watch与 free命令用来实时监控内存使用情况:
代码如下:
#watch -n 2 -d free
Every 2.0s: free Fri Jul 6 06:06:12 2007
total used free shared buffers cached
Mem: 233356 218616 14740 0 5560 64784
-/+ buffers/cache: 148272 85084
Swap: 622584 6656 615928
watch命令会每两秒执行 free一次,执行前会清除屏幕,在同样位置显示数据。因为 watch命令不会卷动屏幕,所以适合出长时间的监测内存使用率。可以使用 -n选项,控制执行的频率也可以利用 -d选项,让命令将每次不同的地方显示出来。Watch命令会一直执行,直到您按下 [Ctrl]-[C] 为止。
二、虚拟内存的概念
(1)Linux虚拟内存实现机制
Linux虚拟内存的实现需要六种机制的支持:地址映射机制、内存分配回收机制、缓存和刷新机制、请求页机制、交换机制、内存共享机制。
首先内存管理程序通过映射机制把用户程序的逻辑地址映射到物理地址,在用户程序运行时如果发现程序中要用的虚地址没有对应的物理内存时,就发出了请求页要求如果有空闲的内存可供分配,就请求分配内存(于是用到了内存的分配和回收),并把正在使用的物理页记录在缓存中(使用了缓存机制)。 如果没有足够的内存可供分配,那么就调用交换机制,腾出一部分内存。另外在地址映射中要通过TLB(翻译后援存储器)来寻找物理页交换机制中也要用到交换缓存,并且把物理页内容交换到交换文件中后也要修改页表来映射文件地址。
(2)虚拟内存容量设定
也许有人告诉你,应该分配2倍于物理内存的虚拟内存,但这是个不固定的规律。如果你的物理保存比较小,可以这样设定。如果你有1G物理内存或更多的话,可以缩小一下虚拟内存。Linux会把大量的内存用做Cache的,但在资源紧张时回收回.。你只要看到swap为0或者很小就可以放心了,因为内存放着不用才是最大的浪费。
三、使甩vmstat命令监视虚拟内存使用情况
vmstat是Virtual Meomory Statistics(虚拟内存统计)的缩写,可对 *** 作系统的虚拟内存、进程、CPU活动进行监视。它是对系统的整体情况进行统计,不足之处是无法对某个进程进行深入分析。通常使用vmstat 5 5(表示在5秒时间内进行5次采样)命令测试。将得到一个数据汇总它可以反映真正的系统情况。
代码如下:
#vmstat 5 5
procs -----------memory---------- ---swap-- -----io---- --system-- ----cpu----
r b swpd free buff cache si so bi bo in cs us sy id wa
1 0 62792 3460 9116 88092 6 30 189 89 1061 569 17 28 54 2
0 0 62792 3400 9124 88092 0 0 0 14 884 434 4 14 81 0
0 0 62792 3400 9132 88092 0 0 0 14 877 424 4 15 81 0
1 0 62792 3400 9140 88092 0 0 0 14 868 418 6 20 74 0
1 0 62792 3400 9148 88092 0 0 0 15 847 400 9 25 67 0
vmstat命令输出分成六个部分:
(1)进程procs:
r:在运行队列中等待的进程数 。
b:在等待io的进程数 。
(2)内存memoy:
swpd:现时可用的交换内存(单位KB)。
free:空闲的内存(单位KB)。
buff: 缓冲去中的内存数(单位:KB)。
cache:被用来做为高速缓存的内存数(单位:KB)。
(3) swap交换页面
si: 从磁盘交换到内存的交换页数量,单位:KB/秒。
so: 从内存交换到磁盘的交换页数量,单位:KB/秒。
(4) io块设备:
bi: 发送到块设备的块数,单位:块/秒。
bo: 从块设备接收到的块数,单位:块/秒。
(5)system系统:
in: 每秒的中断数,包括时钟中断。
cs: 每秒的环境(上下文)切换次数。
(6)cpu中央处理器:
cs:用户进程使用的时间 。以百分比表示。
sy:系统进程使用的时间。 以百分比表示。
id:中央处理器的空闲时间 。以百分比表示。
如果 r经常大于 4 ,且id经常小于40,表示中央处理器的负荷很重。 如果bi,bo 长期不等于0,表示物理内存容量太小。
四、Linux 服务器的内存泄露和回收内存的方法
1、内存泄漏的定义:
一般我们常说的内存泄漏是指堆内存的泄漏。堆内存是指程序从堆中分配的,大小任意的(内存块的大小可以在程序运行期决定),使用完后必须显示释放的内存。应用程序一般使用malloc,realloc,new等函数从堆中分配到一块内存,使用完后,程序必须负责相应的调用free或释放该内存块,否则,这块内存就不能被再次使用,我们就说这块内存泄漏了。
2、内存泄露的危害
从用户使用程序的角度来看,内存泄漏本身不会产生什么危害,作为一般的用户,根本感觉不到内存泄漏的存在。真正有危害的`是内存泄漏的堆积,这会最终消耗尽系统所有的内存。从这个角度来说,一次性内存泄漏并没有什么危害,因为它不会堆积,而隐式内存泄漏危害性则非常大,因为较之于常发性和偶发性内存泄漏它更难被检测到。存在内存泄漏问题的程序除了会占用更多的内存外,还会使程序的性能急剧下降。对于服务器而言,如果出现这种情况,即使系统不崩溃,也会严重影响使用。
3、内存泄露的检测和回收
对于内存溢出之类的麻烦可能大家在编写指针比较多的复杂的程序的时候就会遇到。在 Linux 或者 unix 下,C、C++语言是最使用工具。但是我们的 C++ 程序缺乏相应的手段来检测内存信息,而只能使用 top 指令观察进程的动态内存总额。而且程序退出时,我们无法获知任何内存泄漏信息。
使用kill命令
使用Linux命令回收内存,我们可以使用Ps、Kill两个命令检测内存使用情况和进行回收。在使用超级用户权限时使用命令“Ps”,它会列出所有正在运行的程序名称,和对应的进程号(PID)。Kill命令的工作原理是:向Linux *** 作系统的内核送出一个系统 *** 作信号和程序的进程号(PID)。
应用例子:
为了高效率回收内存可以使用命令ps 参数v:
代码如下:
[root@www ~]# ps v
PID TTY STAT TIME MAJFL TRS DRS RSS %MEM COMMAND
2542 tty1 Ss+ 0:00 0 8 1627 428 0.1 /sbin/mingetty tty1
2543 tty2 Ss+ 0:00 0 8 1631 428 0.1 /sbin/mingetty tty2
2547 tty3 Ss+ 0:00 0 8 1631 432 0.1 /sbin/mingetty tty3
2548 tty4 Ss+ 0:00 0 8 1627 428 0.1 /sbin/mingetty tty4
2574 tty5 Ss+ 0:00 0 8 1631 432 0.1 /sbin/mingetty tty5
2587 tty6 Ss+ 0:00 0 8 1627 424 0.1 /sbin/mingetty tty6
2657 tty7 Ss+ 1:18 12 1710 29981 7040 3.0 /usr/bin/Xorg :0 -br -a
2670 pts/2 Ss 0:01 2 682 6213 1496 0.6 -bash
3008 pts/4 Ss 0:00 2 682 6221 1472 0.6 /bin/bash
3029 pts/4 S+ 0:00 2 32 1783 548 0.2 ping 192.168.1.12
3030 pts/2 R+ 0:00 2 73 5134 768 0.3 ps v
然后如果想回收Ping命令的内存的话,使用命令:
代码如下:
# Kill -9 3029
使用工具软件
Memprof是一个非常具有吸引力且非常易于使用的软件,它由Red Hat的Owen Talyor创立。这个工具是用于GNOME前端的Boehm-Demers-Weiser垃圾回收器。这个工具直接就可以执行,并且其工作起来无需对源代码进行任何修改。在程序执行时,这个工具会以图形化的方式显示内存的使用情况。
相关介绍:Linux
严格来讲,Linux这个词本身只表示Linux内核,但人们已经习惯了用Linux来形容整个基于Linux内核,并且使用GNU 工程各种工具和数据库的 *** 作系统。
Linux拥有以下特性:类似于Unix的基本思想,支持完全免费与自由传播,完全兼容POSIX1.0标准,支持多用户、多任务、有着良好的界面、支持多种平台。Linux 能运行主要的UNIX工具软件、应用程序和网络协议。它支持32位和64位硬件。Linux继承了Unix以网络为核心的设计思想,是一个性能稳定的多用户网络 *** 作系统。
Linux有着许多不同的版本,但它们都使用了Linux内核。Linux可安装在各种计算机硬件设备中,比如手机、平板电脑、路由器、视频游戏控制台、台式计算机、大型机和超级计算机。
页表用来把虚拟页映射到物理页,并且存放页的保护位(即访问权限)。
在Linux4.11版本以前,Linux内核把页表分为4级:
页全局目录表(PGD)、页上层目录(PUD)、页中间目录(PMD)、直接页表(PT) 。
4.11版本把页表扩展到5级,在页全局目录和页上层目录之间增加了 页四级目录(P4D) 。
各处处理器架构可以选择使用5级,4级,3级或者2级页表,同一种处理器在页长度不同的情况可能选择不同的页表级数。可以使用配置宏CONFIG_PGTABLE_LEVELS配置页表的级数,一般使用默认值。
如果选择4级页表,那么使用PGD,PUD,PMD,PT;如果使用3级页表,那么使用PGD,PMD,PT;如果选择2级页表,那么使用PGD和PT。 如果不使用页中间目录 ,那么内核模拟页中间目录,调用函数pmd_offset 根据页上层目录表项和虚拟地址获取页中间目录表项时 , 直接把页上层目录表项指针强制转换成页中间目录表项 。
每个进程有独立的页表,进程的mm_struct实例的成员pgd指向页全局目录,前面四级页表的表项存放下一级页表的起始地址,直接页表的页表项存放页帧号(PFN) 。
内核也有一个页表, 0号内核线程的进程描述符init_task的成员active_mm指向内存描述符init_mm,内存描述符init_mm的成员pgd指向内核的页全局目录swapper_pg_dir 。
ARM64处理器把页表称为转换表,最多4级。ARM64处理器支持三种页长度:4KB,16KB,64KB。页长度和虚拟地址的宽度决定了转换表的级数,在虚拟地址的宽度为48位的条件下,页长度和转换表级数的关系如下所示:
ARM64处理器把表项称为描述符,使用64位的长描述符格式。描述符的0bit指示描述符是不是有效的:0表示无效,1表示有效。第1位指定描述符类型。
在块描述符和页描述符中,内存属性被拆分为一个高属性和一个低属性块。
处理器的MMU负责把虚拟地址转换成物理地址,为了改进虚拟地址到物理地址的转换速度,避免每次转换都需要查询内存中的页表,处理器厂商在管理单元里加了称为TLB的高速缓存,TLB直译为转换后备缓冲区,意译为页表缓存。
页表缓存用来缓存最近使用过的页表项, 有些处理器使用两级页表缓存 : 第一级TLB分为指令TLB和数据TLB,好处是取指令和取数据可以并行;第二级TLB是统一TLB,即指令和数据共用的TLB 。
不同处理器架构的TLB表项的格式不同。ARM64处理器的每条TLB表项不仅包含虚拟地址和物理地址,也包含属性:内存类型、缓存策略、访问权限、地址空间标识符(ASID)和虚拟机标识符(VMID)。 地址空间标识符区分不同进程的页表项 , 虚拟机标识符区分不同虚拟机的页表项 。
如果内核修改了可能缓存在TLB里面的页表项,那么内核必须负责使旧的TLB表项失效,内核定义了每种处理器架构必须实现的函数。
当TLB没有命中的时候,ARM64处理器的MMU自动遍历内存中的页表,把页表项复制到TLB,不需要软件把页表项写到TLB,所以ARM64架构没有提供写TLB的指令。
为了减少在进程切换时清空页表缓存的需要,ARM64处理器的页表缓存使用非全局位区分内核和进程的页表项(nG位为0表示内核的页表项), 使用地址空间标识符(ASID)区分不同进程的页表项 。
ARM64处理器的ASID长度是由具体实现定义的,可以选择8位或者16位。寄存器TTBR0_EL1或者TTBR1_EL1都可以用来存放当前进程的ASID,通常使用寄存器TCR_EL1的A1位决定使用哪个寄存器存放当前进程的ASID,通常使用寄存器 TTBR0_EL1 。寄存器TTBR0_EL1的位[63:48]或者[63:56]存放当前进程的ASID,位[47:1]存放当前进程的页全局目录的物理地址。
在SMP系统中,ARM64架构要求ASID在处理器的所有核是唯一的。假设ASID为8位,ASID只有256个值,其中0是保留值,可分配的ASID范围1~255,进程的数量可能超过255,两个进程的ASID可能相同,内核引入ASID版本号解决这个问题。
(1)每个进程有一个64位的软件ASID, 低8位存放硬件ASID,高56位存放ASID版本号 。
(2) 64位全局变量asid_generation的高56位保存全局ASID版本号 。
(3) 当进程被调度时,比较进程的ASID版本号和全局版本号 。如果版本号相同,那么直接使用上次分配的ASID,否则需要给进程重新分配硬件ASID。
存在空闲ASID,那么选择一个分配给进程。不存在空闲ASID时,把全局ASID版本号加1,重新从1开始分配硬件ASID,即硬件ASID从255回绕到1。因为刚分配的硬件ASID可能和某个进程的ASID相同,只是ASID版本号不同,页表缓存可能包含了这个进程的页表项,所以必须把所有处理器的页表缓存清空。
引入ASID版本号的好处是:避免每次进程切换都需要清空页表缓存,只需要在硬件ASID回环时把处理器的页表缓存清空 。
虚拟机里面运行的客户 *** 作系统的虚拟地址转物理地址分两个阶段:
(1) 把虚拟地址转换成中间物理地址,由客户 *** 作系统的内核控制 ,和非虚拟化的转换过程相同。
(2) 把中间物理地址转换成物理地址,由虚拟机监控器控制 ,虚拟机监控器为每个虚拟机维护一个转换表,分配一个虚拟机标识符,寄存器 VTTBR_EL2 存放当前虚拟机的阶段2转换表的物理地址。
每个虚拟机有独立的ASID空间 ,页表缓存使用 虚拟机标识符 区分不同虚拟机的转换表项,避免每次虚拟机切换都要清空页表缓存,在虚拟机标识符回绕时把处理器的页表缓存清空。
什么是虚拟内存?Linux支持虚拟内存(virtual memory),虚拟内存是指使用磁盘当作RAM的扩展,这样可用的内存的大小就相应地增大了。内核会将暂时不用的内存块的内容写到硬盘上,这样一来,这块内存就可用于其它目的。当需要用到原始的内容时,它们被重新读入内存。这些 *** 作对用户来说是完全透明的;Linux下运行的程序只是看到有大量的内存可供使用而并没有注意到时不时它们的一部分是驻留在硬盘上的。当然,读写硬盘要比直接使用真实内存慢得多(要慢数千倍),所以程序就不会象一直在内存中运行的那样快。用作虚拟内存的硬盘部分被称为交换空间(swap space)。
Linux能够使用文件系统中的一个常规文件或一个独立的分区作为交换空间。交换分区要快一些,但是很容易改变交换文件的大小(也就无需重分区整个硬盘,并且可以从临时分区中安装任何东西)。当你知道你需要多大的交换空间时,你应该使用交换分区,但是如果你不能确定的话,你可以首先使用一个交换文件,然后使用一阵子系统,你就可以感觉到要有多大的交换空间,此时,当你能够确信它的大小时就创建一个交换分区。
你应该知道,Linux允许同时使用几个交换分区以及/或者交换文件。这意味着如果你只是偶尔地另外需要一个交换空间时,你可以在当时设置一个额外的交换文件,而不是一直分配这个交换空间。
*** 作系统术语注释:计算机科学常常将交换[swapping](将整个进程写到交换空间)与页面调度[paging](在某个时刻,仅仅固定大小的几千字节写到交换空间内)加以区别。页面调度通常更有效,这也是Linux的做法,但是传统的Linux术语却指的是交换。
创建交换空间
一个交换文件是一个普通的文件;对内核来说一点也不特殊。对内核有关系的是它不能有孔,并且它是用mkswap来准备的。而且,它必须驻留在一个本地硬盘上,它不能由于实现的原因而驻留在一个通过NFS加载的文件系统中。
关于孔是重要的。交换文件保留了磁盘空间,以至于内核能够快速地交换出页面而无需做分配磁盘扇区给文件时所要做的一些事。内核仅仅是使用早已分配给交换文件的任何扇区而已。因为文件中的一个孔意味着没有磁盘扇区分配(给该文件的孔的相应部分),对内核来说就不能使用这类有孔的文件。
创建无孔的交换文件的一个好方法是通过下列命令:
$ dd if=/dev/zero of=/extra-swap bs=1024 count=1024 \
上面/extra-swap是交换文件的名字,大小由count=后面的数值给出。大小最好是4的倍数,因为内核写出的内存页面(memory pages)大小是4千字节。如果大小不是4的倍数,最后几千字节就用不上了。
一个交换分区也并没有什么特别的。你可以象创建其它分区一样地创建它;唯一的区别在于它是作为一个原始的分区使用的,也即,它不包括任何的文件系统。将交换分区标记为类型82(Linux交换分区)是个好主意;这将使得分区的列表更清楚,尽管对内核来说并不是一定要这样的。
在创建了一个交换文件或一个交换分区以后,你必须在它的开头部分写上一个签名;这个签名中包括了一些由内核使用的管理信息。这是用\cmd{mkswap}命令来做到的,用法如下:
$ mkswap /extra-swap 1024
Setting up swapspace, size = 1044480 bytes
请注意此时交换空间还没有被使用:它已存在,但内核还没有用它作为虚拟内存。你必须非常小心地使用mkswap,因为它不检查这个文件或分区是否已被别人使用。你可以非常容易地使用mkswap来覆盖重要的文件以及分区!幸运的是,仅仅在安装系统时,你才需要使用mkswap。
Linux内存管理程序限制每个交换空间最大约为127MB(由于各种技术上的原因,实际的限制大小为(4096-10) * 8 * 4096 = 133890048$ 字节,或127.6875兆字节)。然而,你可以同时使用多至16个交换空间,总容量几乎达2GB。
交换空间的使用
一个已初始化的交换空间是使用命令swapon投入正式使用的。该命令告诉内核这个交换空间可以被使用了。到交换空间的路径是作为参数给出的,所以,开始在一个临时交换文件上使用交换的命令如下:
$ swapon /extra-swap
通过把交换空间列入/etc/fstab文件中就能被自动地使用了。
/dev/hda8 none swap sw 0 0
/swapfile none swap sw 0 0
启动描述文件会执行命令swapon –a,这个命令会启动列于/etc/fstab中的所有交换空间。因此,swapon命令通常仅用于需要有外加的交换空间时。
你可以用free命令监视交换空间的使用情况。它将给出已使用了多少的交换空间。
total used free shared buffers
Swap: 32452 6684 25768
输出的第一行(Mem:)显示出物理内存的使用情况。总和(total)列中并没有显示出被内核使用的内存,它通常将近一兆字节。已用列(used column)显示出已用内存的总和(第二行没有把缓冲算进来)。空闲列(free column)显示了所有未被使用的空闲内存。共享列(shared column)显示出了被几个进程共享的内存的大小;共享的内存越多,情况就越好。缓存列(buffer column)显示出了当前磁盘缓存的大小。已缓冲列(cached column)显示出了已使用的缓存的大小。
最后一行(Swap:)显示出了与交换空间相应的信息。如果这一行的数值都是零,表示你的交换空间没有被击活。
也可通过用top命令来获得同样的信息,或者使用proc文件系统中的文件/proc/meminfo 。通常要取得指定交换空间的使用情况是困难的。
可以使用命令swapoff来移去一个交换空间。通常没有必要这样做,但临时交换空间除外。一般,在交换空间中的页面首先被换入内存;如果此时没有足够的物理内存来容纳它们又将被交换出来(到其他的交换空间中)。如果没有足够的虚拟内存来容纳所有这些页面,Linux就会波动而不正常;但经过一段较长的时间Linux会恢复,但此时系统已不可用了。在移去一个交换空间之前,你应该检查(例如,用free)是否有足够的空闲内存。
任何由swapon –a而自动被使用的所有交换空间都能够用swapoff –a命令移去;该命令参考/etc/fstab文件来确定移去什么。任何手工设置使用的交换空间将始终可以被使用。
有时,尽管有许多的空闲内存,仍然会有许多的交换空间正被使用。这是有可能发生的,例如如果在某一时刻有进行交换的必要,但后来一个占用很多物理内存的大进程结束并释放内存时。被交换出的数据并不会自动地交换进内存,除非有这个需要时。此时物理内存会在一段时间内保持空闲状态。对此并没有什么可担心的,但是知道了是怎么一回事我们也就放心了。
许多 *** 作系统使用了虚拟内存的方法。因为它们仅在运行时才需要交换空间,以即决不会在同一时间使用交换空间,因此,除了当前正在运行的 *** 作系统的交换空间,其它的就是一种浪费。所以让它们共享一个交换空间将会更有效率。这是可能的,但需要有一定的了解。在HOWTO技巧文档中含有如何实现这种做法的一些建议。
有些人会对你说需要用物理内存的两倍容量来分配交换空间,但这是不对的。下面是合适的做法:
。估计你的总内存需求。这是某一时刻你所需要的最大的内存容量,也就是在同一时刻你想运行的所有程序所需内存的总和。通过同时运行所有的程序你可以做到这一点。
例如,如果你要运行X,你将给它分配大约8MB内存,gcc需要几兆字节(有些文件要求异呼寻常的大量的内存量,多至几十兆字节,但通常约4兆字节应该够了),等等。内核本身要用大约1兆字节、普通的shell以及其它一些工具可能需要几百千字节(就说总和要1兆字节吧)。并不需要进行精确的计算,粗率的估计也就足够了,但你必须考虑到最坏的情况。
注意,如果会有几个人同时使用这个系统,他们都将消耗内存。然而,如果两个人同时运行一个程序,内存消耗的总量并不是翻倍,因为代码页以及共享的库只存在一份。
Free以及ps命令对估计所需的内存容量是很有帮助的。
对第一步中的估计放宽一些。这是因为对程序在内存中占用多少的估计通常是不准的,因为你很可能忘掉几个你要运行的程序,以及,确信你还要有一些多余的空间用于以防万一。这需几兆字节就够了。(多分配总比少分配交换空间要好,但并不需要过分这样以至于使用整个硬盘,因为不用的交换空间是浪费的空间;参见后面的有关增加交换空间。)同样,因为处理数值更好做,你可以将容量值加大到整数兆字节。
基于上面的计算,你就知道了你将需要总和为多少的内存。所以,为了分配交换空间,你仅需从所需总内存量中减去实际物理内存的容量,你就知道了你需要多少的交换空间。(在某些UNIX版本中,你还需要为物理内存的映像分配空间,所以第二步中算出的总量正是你所需要的交换空间的容量,而无需再做上述中的减法运算了。)
如果你计算出的交换空间容量远远大于你的物理内存(大于两倍以上),你通常需要再买些内存来,否则的话,系统的性能将非常低。
有几个交换空间是个好主意,即使计算指出你一个都不需要。Linux系统常常动不动就使用交换空间,以保持尽可能多的空闲物理内存。即使并没有什么事情需要内存,Linux也会交换出暂时不用的内存页面。这可以避免等待交换所需的时间:当磁盘闲着,就可以提前做好交换。
可以将交换空间分散在几个硬盘之上。针对相关磁盘的速度以及对磁盘的访问模式,这样做可以提高性能。你可能想实验几个方案,但是你要认识到这些实验常常是非常困难的。不要相信其中一个方案比另一个好的说法,因为并不总是这样的。
高速缓冲
与访问(真正的)的内存相比,磁盘[3]的读写是很慢的。另外,在相应较短的时间内多次读磁盘同样的部分也是常有的事。例如,某人也许首先阅读了一段e-mail消息,然后为了答复又将这段消息读入编辑器中,然后又在将这个消息拷贝到文件夹中时,使得邮件程序又一次读入它。或者考虑一下在一个有着许多用户的系统中ls命令会被使用多少次。通过将信息从磁盘上仅读入一次并将其存于内存中,除了第一次读以外,可以加快所有其它读的速度。这叫作磁盘缓冲(disk buffering),被用作此目的的内存称为高速缓冲(buffer cache)。
不幸的是,由于内存是一种有限而又不充足的资源,高速缓冲不可能做的很大(它不可能包容要用到的所有数据)。当缓冲充满了数据时,其中最长时间不用的数据将被舍弃以腾出内存空间用于新的数据。
对写磁盘 *** 作来说磁盘缓冲技术同样有效。一方面,被写入磁盘的数据常常会很快地又被读出(例如,原代码文件被保存到一个文件中,又被编译器读入),所以将要被写的数据放入缓冲中是个好主意。另一方面,通过将数据放入缓冲中,而不是将其立刻写入磁盘,程序可以加快运行的速度。以后,写的 *** 作可以在后台完成,而不会拖延程序的执行。
大多数 *** 作系统都有高速缓冲(尽管可能称呼不同),但是并不是都遵守上面的原理。有些是直接写(write-through):数据将被立刻写入磁盘(当然,数据也被放入缓存中)。如果写 *** 作是在以后做的,那么该缓存被称为后台写(write-back)。后台写比直接写更有效,但也容易出错:如果机器崩溃,或者突然掉电,或者是软盘在缓冲中等待写的数据被写入软盘之前被从驱动器中取走,缓冲中改变过的数据就被丢失了。如果仍未被写入的数据含有重要的薄记信息,这甚至可能意味着文件系统(如果有的话)已不完整。
由于上述原因,在使用适当的关闭过程之前,绝对不要关掉电源(见第六章),不要在卸载(如果已被加载)之前将软盘从驱动器中取出来,也不要在任何正在使用软盘的程序指示出完成了软盘 *** 作并且软盘灯熄灭之前将软盘取出来。sync命令倾空(flushes)缓冲,也即,强迫所有未被写的数据写入磁盘,可用以确定所有的写 *** 作都已完成。在传统的UNIX系统中,有一个叫做update的程序运行于后台,每隔30秒做一次sync *** 作,因此通常无需手工使用sync命令了。Linux另外有一个后台程序,bdflush,这个程序执行更频繁的但不是全面的同步 *** 作,以避免有时sync的大量磁盘I/O *** 作所带来的磁盘的突然冻结。
在Linux中,bdflush是由update启动的。通常没有理由来担心此事,但如果由于某些原因bdflush进程死掉了,内核会对此作出警告,此时你就要手工地启动它了(/sbin/update)。
缓存(cache)实际并不是缓冲文件的,而是缓冲块的,块是磁盘I/O *** 作的最小单元(在Linux中,它们通常是1KB)。这样,目录、超级块、其它文件系统的薄记数据以及非文件系统的磁盘数据都可以被缓冲了。
缓冲的效力主要是由它的大小决定的。缓冲大小太小的话等于没用:它只能容纳一点数据,因此在被重用时,所有缓冲的数据都将被倾空。实际的大小依赖于数据读写的频次、相同数据被访问的频率。只有用实验的方法才能知道。
如果缓存有固定的大小,那么缓存太大了也不好,因为这会使得空闲的内存太小而导致进行交换 *** 作(这同样是慢的)。为了最有效地使用实际内存,Linux自动地使用所有空闲的内存作为高速缓冲,当程序需要更多的内存时,它也会自动地减小缓冲的大小。
在Linux中,你不需要为使用缓冲做任何事情,它是完全自动处理的。除了上面所提到的有关按照适当的步骤来关机和取出软盘,你不用担心它。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)