揭开Linux操作系统的Swap交换区之谜

Swap,即交换区,除了安装Linux的时候,有多少人关心过它呢?其实,Swap的调整对Linux服务器,特别是Web服务器的性能至关重要。通过调整Swap,有时可以越过系统性能瓶颈,节省系统升级费用。

  Swap的原理是一个较复杂的问题,需要大量的篇幅来说明。在这里只作简单的介绍,在以后的文章中将和大家详细讨论Swap实现的细节。

  众所周知,现代操作系统都实现了“虚拟内存”这一技术,不但在功能上突破了物理内存的限制,使程序可以操纵大于实际物理内存的空间,更重要的是,“虚拟内存”是隔离每个进程的安全保护网,使每个进程都不受其它程序的干扰。

  Swap空间的作用可简单描述为:当系统的物理内存不够用的时候,就需要将物理内存中的一部分空间释放出来,以供当前运行的程序使用。那些被释放的空间可能来自一些很长时间没有什么操作的程序,这些被释放的空间被临时保存到Swap空间中,等到那些程序要运行时,再从Swap中恢复保存的数据到内存中。这样,系统总是在物理内存不够时,才进行Swap交换。

  计算机用户会经常遇这种现象。例如,在使用Windows系统时,可以同时运行多个程序,当你切换到一个很长时间没有理会的程序时,会听到硬盘“哗哗”直响。这是因为这个程序的内存被那些频繁运行的程序给“偷走”了,放到了Swap区中。因此,一旦此程序被放置到前端,它就会从Swap区取回自己的数据,将其放进内存,然后接着运行。

  需要说明一点,并不是所有从物理内存中交换出来的数据都会被放到Swap中(如果这样的话,Swap就会不堪重负),有相当一部分数据被直接交换到文件系统。例如,有的程序会打开一些文件,对文件进行读写(其实每个程序都至少要打开一个文件,那就是运行程序本身),当需要将这些程序的内存空间交换出去时,就没有必要将文件部分的数据放到Swap空间中了,而可以直接将其放到文件里去。如果是读文件操作,那么内存数据被直接释放,不需要交换出来,因为下次需要时,可直接从文件系统恢复;如果是写文件,只需要将变化的数据保存到文件中,以便恢复。但是那些用malloc和new函数生成的对象的数据则不同,它们需要Swap空间,因为它们在文件系统中没有相应的“储备”文件,因此被称作“匿名”(Anonymous)内存数据。这类数据还包括堆栈中的一些状态和变量数据等。所以说,Swap空间是“匿名”数据的交换空间。

  突破128M Swap限制

  经常看到有些Linux(国内汉化版)安装手册上有这样的说明:Swap空间不能超过128M。为什么会有这种说法?在说明“128M”这个数字的来历之前,先给问题一个回答:现在根本不存在128M的限制!现在的限制是2G!

  Swap空间是分页的,每一页的大小和内存页的大小一样,方便Swap空间和内存之间的数据交换。旧版本的Linux实现Swap空间时,用Swap空间的第一页作为所有Swap空间页的一个“位映射”(Bit map)。这就是说第一页的每一位,都对应着一页Swap空间。如果这一位是1,表示此页Swap可用;如果是0,表示此页是坏块,不能使用。这么说来,第一个Swap映射位应该是0,因为,第一页Swap是映射页。另外,最后10个映射位也被占用,用来表示Swap的版本(原来的版本是Swap_space ,现在的版本是swapspace2)。那么,如果说一页的大小为s,这种Swap的实现方法共能管理“8 * ( s - 10 ) - 1”个Swap页。对于i386系统来说s=4096,则空间大小共为133890048,如果认为1 MB=2^20 Byte的话,大小正好为128M。

  之所以这样来实现Swap空间的管理,是要防止Swap空间中有坏块。如果系统检查到Swap中有坏块,则在相应的位映射上标记上0,表示此页不可用。这样在使用Swap时,不至于用到坏块,而使系统产生错误。

  现在的系统设计者认为:

  1.现在硬盘质量很好,坏块很少。

  2.就算有,也不多,只需要将坏块罗列出来,而不需要为每一页建立映射。

  3.如果有很多坏块,就不应该将此硬盘作为Swap空间使用。

  于是,现在的Linux取消了位映射的方法,也就取消了128M的限制。直接用地址访问,限制为2G。

  Swap配置对性能的影响

  分配太多的Swap空间会浪费磁盘空间,而Swap空间太少,则系统会发生错误。 如果系统的物理内存用光了,系统就会跑得很慢,但仍能运行;如果Swap空间用光了,那么系统就会发生错误。例如,Web服务器能根据不同的请求数量衍生出多个服务进程(或线程),如果Swap空间用完,则服务进程无法启动,通常会出现“application is out of memory”的错误,严重时会造成服务进程的死锁。因此Swap空间的分配是很重要的。

通常情况下,Swap空间应大于或等于物理内存的大小,最小不应小于64M,通常Swap空间的大小应是物理内存的2-2.5倍。但根据不同的应用,应有不同的配置:如果是小的桌面系统,则只需要较小的Swap空间,而大的服务器系统则视情况不同需要不同大小的Swap空间。特别是数据库服务器和Web服务器,随着访问量的增加,对Swap空间的要求也会增加,具体配置参见各服务器产品的说明。

  另外,Swap分区的数量对性能也有很大的影响。因为Swap交换的操作是磁盘IO的操作,如果有多个Swap交换区,Swap空间的分配会以轮流的方式操作于所有的Swap,这样会大大均衡IO的负载,加快Swap交换的速度。如果只有一个交换区,所有的交换操作会使交换区变得很忙,使系统大多数时间处于等待状态,效率很低。用性能监视工具就会发现,此时的CPU并不很忙,而系统却慢。这说明,瓶颈在IO上,依靠提高CPU的速度是解决不了问题的。

  系统性能监视

  Swap空间的分配固然很重要,而系统运行时的性能监控却更加有价值。通过性能监视工具,可以检查系统的各项性能指标,找到系统性能的瓶颈。本文只介绍一下在Solaris下和Swap相关的一些命令和用途。

  最常用的是Vmstat命令(在大多数Unix平台下都有这样一些命令),此命令可以查看大多数性能指标。

  例如:

  

  命令说明:

  vmstat 后面的参数指定了性能指标捕获的时间间隔。3表示每三秒钟捕获一次。第一行数据不用看,没有价值,它仅反映开机以来的平均性能。从第二行开始,反映每三秒钟之内的系统性能指标。这些性能指标中和Swap有关的包括以下几项:

  procs下的w

  它表示当前(三秒钟之内)需要释放内存、交换出去的进程数量。

  memory下的swpd

  它表示使用的Swap空间的大小。

  Swap下的si,so

  si表示当前(三秒钟之内)每秒交换回内存(Swap in)的总量,单位为kbytes;so表示当前(三秒钟之内)每秒交换出内存(Swap out)的总量,单位为kbytes。

  以上的指标数量越大,表示系统越忙。这些指标所表现的系统繁忙程度,与系统具体的配置有关。系统管理员应该在平时系统正常运行时,记下这些指标的数值,在系统发生问题的时候,再进行比较,就会很快发现问题,并制定本系统正常运行的标准指标值,以供性能监控使用。

  另外,使用Swapon-s也能简单地查看当前Swap资源的使用情况。例如:

 能够方便地看出Swap空间的已用和未用资源的大小。

  应该使Swap负载保持在30%以下,这样才能保证系统的良好性能。

  有关Swap操作的系统命令

  增加Swap空间,分以下几步:

  1)成为超级用户

  $su - root

  2)创建Swap文件

  # dd if=/dev/zero of=swapfile bs=1024 count=65536

  创建一个有连续空间的交换文件。

  3)激活Swap文件

  #/usr/sbin/swapon swapfile

  swapfile指的是上一步创建的交换文件。 4)现在新加的Swap文件已经起作用了,但系统重新启动以后,并不会记住前几步的操作。因此要在/etc/fstab文件中记录文件的名字,和Swap类型,如:

  /path/swapfile none Swap sw,pri=3 0 0

  5)检验Swap文件是否加上

  /usr/sbin/swapon -s

  删除多余的Swap空间。

  1)成为超级用户

  2)使用Swapoff命令收回Swap空间。

  #/usr/sbin/swapoff swapfile

  3)编辑/etc/fstab文件,去掉此Swap文件的实体。

  4)从文件系统中回收此文件。

  #rm swapfile

  5)当然,如果此Swap空间不是一个文件,而是一个分区,则需创建一个新的文件系统,再挂接到原来的文件系统上。

linux如何获取每个进程使用了多少swap

一系统使用的swap比较多

[root@localhost ~]# free -m

total       used       free     shared    buffers     cached

Mem:          3952       3905         47          0        417       1342

-/+ buffers/cache:       2145       1807

Swap:         6997       3599       3397

用free可以看到使用了3599M交换空间,接下来就想知道这些swap都被哪些进程使用了。刚开始用top来看,top->按f->按p,然后按空格退出,排一下序,看到结果如下:

PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  SWAP COMMAND

32564 root      15   0 1789m 8192 1464 S  0.0  0.2  13:36.06 1.7g snmpd

22823 usr_zhan  18   0 1406m  38m 2216 S  0.0  1.0  39:40.26 1.3g Java

31687 oracle    18   0 1314m  16m  12m S  0.0  0.4   0:00.01 1.3g oracle

31689 oracle    18   0 1313m  15m  12m S  0.0  0.4   0:00.00 1.3g oracle

31667 oracle    15   0 1313m  16m  12m S  0.0  0.4   0:00.06 1.3g oracle

31665 oracle    15   0 1314m  17m  14m S  0.0  0.5   0:00.05 1.3g oracle

31854 oracle    15   0 1328m  32m  18m S  0.0  0.8   0:00.54 1.3g oracle

31856 oracle    15   0 1339m  45m  20m S  0.0  1.1   0:01.47 1.3g oracle

602 oracle    18   0 1313m  19m  16m S  0.0  0.5   0:00.02 1.3g oracle

31679 oracle    18   0 1313m  22m  19m S  0.0  0.6   0:00.01 1.3g oracle

31685 oracle    15   0 1313m  22m  19m S  0.0  0.6   0:00.04 1.3g oracle

31669 oracle    15   0 1313m  28m  24m S  0.0  0.7   0:00.06 1.3g oracle

31675 oracle    16   0 1314m  31m  27m S  0.0  0.8   0:08.74 1.3g oracle

31673 oracle    15   0 1328m  46m  42m S  0.0  1.2   0:02.38 1.3g oracle

604 oracle    15   0 1315m  40m  35m S  0.0  1.0   0:09.68 1.2g oracle

31681 oracle    15   0 1320m  50m  42m S  0.0  1.3   0:03.46 1.2g oracle

600 oracle    15   0 1315m  48m  43m S  0.0  1.2   0:01.21 1.2g oracle

16575 oracle    15   0 1315m  60m  56m S  0.0  1.5   0:03.92 1.2g oracle

31869 oracle    15   0 1316m  63m  58m S  0.0  1.6   0:01.26 1.2g oracle

606 oracle    15   0 1316m  66m  60m S  0.0  1.7   0:25.94 1.2g oracle

31683 oracle    15   0 1318m  80m  73m S  0.0  2.0   0:07.52 1.2g oracle

31677 oracle    15   0 1314m  97m  92m S  0.0  2.5   0:03.84 1.2g oracle

31671 oracle    15   0 1317m 126m 120m S  0.0  3.2   0:02.20 1.2g oracle

10497 root      18   0  974m  47m 1992 S  0.0  1.2  14:14.27 927m java

5841 root      21   0 1010m 118m 2116 S  0.0  3.0  17:28.41 891m java

使用swap最多的进程为snmp,用了1.7G,另外使用swap超过1G的还有20多个oracle进程。看了这个就知道这不是我想要的,不管top的SWAP列代表了什么,但肯定不会是代表了进程正在使用的swap数量。

google了下,看到可以用smaps文件来统计,smaps是系统内存接口特性文件,位于/proc/$PID/目录下,文件的内容是进程内存映像信息,如

[root@localhost ~]#cat /proc/22823/smaps

... ...

40108000-4010a000 rwxp 00008000 08:04 9142711         /usr/java/jdk1.6.0_11/bin/java

Size:                 8 kB

Rss:                  0 kB

Shared_Clean:         0 kB

Shared_Dirty:         0 kB

Private_Clean:        0 kB

Private_Dirty:        0 kB

Swap:        8 kB

... ...

在第一行中:

  • 40108000-4010a000是虚拟内存段的开始和结束位置

  • rwxp内存段的权限,最后一位p代表私有,s代表共享

  • 00008000该虚拟内存段在对应的映射文件中的偏移量

  • 08:04文件的主设备和次设备号

  • 9142711被映射到虚拟内存的文件的索引节点号

  • /usr/java/jdk1.6.0_11/bin/java被映射到虚拟内存的文件名称。后面带(deleted)的是内存数据,可以被销毁。

其它:

  • size 是进程使用内存空间,并不一定实际分配了内存(VSS)

  • Rss是实际分配的内存(不需要缺页中断就可以使用的)

  • Pss是平摊计算后的使用内存(有些内存会和其他进程共享,例如mmap进来的)

  • Shared_Clean 和其他进程共享的未改写页面

  • Shared_Dirty 和其他进程共享的已改写页面

  • Private_Clean 未改写的私有页面页面

  • Private_Dirty 已改写的私有页面页面

  • Swap 存在于交换分区的数据大小(如果物理内存有限,可能存在一部分在主存一部分在交换分区)

结果中可能还会有其它项,各项所代表的具体含义可以看http://www.kernel.org/doc/Documentation/filesystems/proc.txt 。

我需要的只是SWAP的数据大小,那么只要把smaps文件的所有swap加起来就可以了,这个也出了脚本,粗略改了下,可统计所有进程各自使用的swap或单个进程使用的swap:

----------------------------------------

#!/bin/bash

PID=${1:-[1-9]*}

total_swap=0

GetSwap () {

pid=$1

cmdline=$(cat /proc/$pid/cmdline 2>/dev/null|tr '' ' ')

pid_swap=$(awk 'BEGIN{total=0}/Swap/{total+=$2}END{print total}' /proc/$pid/smaps 2>/dev/null)

if [ "$pid_swap" != '' ] && [ "$pid_swap" -gt 0 ]; then

echo "PID=$pid – Swap used: $pid_swap Kb – ($cmdline)"

fi

}

cd /proc

for pid in $PID; do

GetSwap $pid

let total_swap+=$pid_swap

done

echo "Total swap: $total_swap Kb"

---------------------------------------

[root@localhost~]# ./getswap.sh

... 略 ...

PID=6235 – Swap used: 416 Kb – (-bash)

PID=631 – Swap used: 404 Kb – (-bash)

PID=6363 – Swap used: 416 Kb – (-bash)

PID=6496 – Swap used: 48 Kb – (tail-f/data/apps/msag/tomcat/logs/catalina.out.2011-08-05)

PID=6535 – Swap used: 2136 Kb – (/usr/libexec/gconfd-25)

PID=6544 – Swap used: 52 Kb – (tail-f/data/apps/msag/tomcat/logs/catalina.out.2011-08-04)

PID=743 – Swap used: 3956 Kb – (/home/oracle/oracle/product/10.2.0/db_2/perl/bin/perl/home/oracle/oracle/product/10.2.0/db_2/bin/emwd.pldbconsole/home/oracle/oracle/product/10.2.0/db_2/server_32_demo/sysman/log/emdb.nohup)

PID=7568 – Swap used: 204 Kb – (/bin/sh/usr/bin/mysqld_safe--datadir=/var/lib/MySQL--socket=/var/lib/mysql/mysql.sock--log-error=/var/log/mysqld.log--pid-file=/var/run/mysqld/mysqld.pid--user=mysql)

PID=7618 – Swap used: 19292 Kb – (/usr/libexec/mysqld--basedir=/usr--datadir=/var/lib/mysql--user=mysql--pid-file=/var/run/mysqld/mysqld.pid--skip-external-locking--socket=/var/lib/mysql/mysql.sock)

PID=8405 – Swap used: 336 Kb – (-bash)

PID=8505 – Swap used: 48 Kb – (tail-f/data/apps/msag/tomcat/logs/catalina.out.2010-04-27)

PID=8693 – Swap used: 2020 Kb – (/home/oracle/oracle/product/10.2.0/db_2/bin/tnslsnrLISTENER-inherit)

Total swap: 3318384 Kb

可以很清楚的看到每个进程使用的swap情况,只是总数和用free得出的结果比较还有出入,少了差不多300多M。然后还有一个问题是在一台oracle数据库中,swap用了差不多5G,但是在smaps文件中却找不到任何的swap使用记录,这个还不知道是什么原因。

 
0

揭开Linux操作系统的Swap交换区之谜的更多相关文章

  1. Linux设置虚拟内存-创建和启用Swap交换区

    如果你的服务器的总是报告内存不足,并且时常因为内存不足而引发服务被强制kill的话,在不增加物理内存的情况下,启用swap交换区作为虚拟内存是一个不错的选择,如果是SSD硬盘,正常读写速度都在300M ...

  2. [Linux]创建和启用Swap交换区

    如果你的服务器的总是报告内存不足,并且时常因为内存不足而引发服务被强制kill的话,在不增加物理内存的情况下,启用swap交换区作为虚拟内存是一个不错的选择,我购买的DigitalOcean VPS ...

  3. mkswap 把一个分区格式化成为swap交换区

    mkswap /dev/sda* //创建此分区为swap 交换分区swapon /dev/sda* //加载交换分区swapoff /dev/sda* //关闭交换分区: 若想要开机自动挂载:vi ...

  4. Linux下swap(交换分区)的增删改

    swap介绍 Linux 的交换分区(swap),或者叫内存置换空间(swap space),是磁盘上的一块区域,可以是一个分区,也可以是一个文件,或者是他们的组合.交换分区的作用是,当系统物理内存吃 ...

  5. Linux基础-swap交换分区

    任务:对一块15G大小的硬盘进行分区,主分区为5G,扩展分区10G,一个逻辑分区5G作为swap交换分区,并激活查看新的swap分区 第一步,建立的新的SCSI硬盘,开启Linux系统前添加一块大小为 ...

  6. linux扩大swap交换空间

    有两种解决方法:一是创建新的swap分区;另一则是创建swap文件 创建swap文件如果你的硬盘空间已经全部分配给其他分区,也没有多余的预算新添购硬盘,我们可以利用swap文件的方式增加虚拟的swap ...

  7. Linux Swap交换分区介绍

    Swap分区在系统的物理内存不够用的时候,把物理内存中的一部分空间释放出来,以供当前运行的程序使用.那些被释放的空间可能来自一些很长时间没有什么操作的程序,这些被释放的空间被临时保存到Swap分区中, ...

  8. 【转】【Linux】Swap与Memory

    背景介绍 Memory指机器物理内存,读写速度低于CPU一个量级,但是高于磁盘不止一个量级.所以,程序和数据如果在内存的话,会有非常快的读写速度.但是,内存的造价是要高于磁盘的,且内存的断电丢失数据也 ...

  9. 问题:Linux报swap空间占用过高,但物理内存还有空余

    报错 收到报警,swap空间占用过高,登录到系统查看内存使用详情,看到物理内存还有很多未使用 问题分析 Swap配置对性能的影响分配太多的Swap空间会浪费磁盘空间,而Swap空间太少,则系统会发生错 ...

随机推荐

  1. Qt Creator 你必须要掌握的快捷操作

    多使用快捷键能显著提高工作效率,尽可能减少键盘,鼠标之间切换所浪费的时间.我这里列出个人认为非常重要必须掌握的 Qt Creator 快捷键.看你知道几个? . 1 .Ctrl(按住)+ Tab快速切 ...

  2. javascript中涉及到汉字的比较

    在使用js中的"=="进行字符串的比较时,发现在英文情况下是ok的,但在中文比较时则不行了. 在网上搜索,提供了一个解决方法,使用 stringObject.localeCompa ...

  3. cocoaPods下载使用记录

    cocoaPods下载使用记录 参考地址: 如何在Mac OS 上安装运行Ruby运行环境 http://www.cnblogs.com/daguo/p/4097263.html cocoaPods安 ...

  4. linux mysql命令

    一: 1.启动 MySQL安装完成后启动文件mysql在/etc/init.d目录下,在需要启动时运行下面命令即可. /etc/init.d/mysql start 2.停止 /usr/bin/mys ...

  5. php 编译安装的一个 configure 配置

    yum -y install libmcrypt-devel mhash-devel libxslt-devel libjpeg libjpeg-devel libpng libpng-devel f ...

  6. 玩javaweb的web.xml编译路径

    有时候能够碰到这样的情况 缓存就是 清不掉 那就可以去寻找编译路径了 <Context docBase="E:\java-workspace\eigyo_com405" pa ...

  7. Premature optimization is the root of all evil.

    For all of we programmers,we should always remember that "Premature optimization is the root of ...

  8. IE浏览器设置

  9. IOS 生成设备唯一标识

    前言 iOS设备5.0以上放弃使用[[UIDevice currentDevice] uniqueIdentifier]来获得设备唯一ID iOS设备私有方法禁止用户获取和使用IMEI 需求 需要一个 ...

  10. javaScript 删除数组中指定元素

    Array.prototype.indexOf = function(val) { for (var i = 0; i < this.length; i++) { if (this[i] == ...