Unix/Linux 系统自动化管理: 内存管理篇
 

2009-12-09 作者:王华忠,杨国梁 来源:IBM

 
本文内容包括:
本文是 Unix/Linux 系统管理自动化系列中的一篇文章,主要介绍了内存管理所涉及的命令,并通过编写自动化脚本实现了内存管理与监控的自动化

内存是 Unix/Linux 内核所管理的最为重要的资源之一,内存管理是系统管理中非常重要也是最复杂的的部分。系统管理员需要掌握内存管理的基本工作原理以及使用合适的工具与策略监控内存的工作状态。 本文将分别阐述 AIX 和 Linux 系统中所涉及到的内存监控的方法,并对其中涉及到的内核内存管理的原理做初步的说明。

AIX 内存管理与监控

内存管理概述

内存管理在不同的操作系统中会有不同的实现。AIX 系统使用 VMM(Virtual Memory Manager) 实现物理内存的管理,处理应用程序的内存分配请求与内存回收。

内存和交换空间一般都是通过页面来进行分配和管理,VMM 将所有的内存段划分为若干个页面,Power4 芯片支持 4K,64K,和 16M 大小的虚拟内存页, Power5 芯片支持 4K,64K,16M,16G 大小的虚拟内存页,每个页面的缺省大小是 4KB。虚拟内存页面越大,对需要大内存块的应用程序可以起到优化作用,主要是提高 TLB 的命中率。

当我们执行应用程序的时候,内存中的页面会被逐渐的占用,这里我们设计两个重要的参数: Minfree( 最小空闲页面的大小 ) 和 Maxfree( 最大空闲页面的大小 )。当空闲的内存达到 Minfree 大小的时候, VMM 的调页算法将被唤醒,将内存中的页面转移到交换空间中, 知道空闲内存达到 Maxfree,才停止调页。

上面主要是对 AIX 内存管理中所涉及到的的基本概念做了简单的介绍说明,对于任何与内存相关的操作,了解这些概念都是非常必要的。

系统管理员在进行正确的优化或者问题发生之前,必须首先监视系统,使用合适的工具捕获基准数据,并且知道如何进行分析工作。下面笔者将介绍 AIX 系统所提供的工具来监控系统内存的使用情况。

内存调整命令

与其他的子系统相比,内存调整更为困难,但同时收到的效果往往更加显著,特别是在那些尚未对各种内存参数进行优化的运行环境中。系统管理员可以通过 vmo 命令动态的调整内存参数,进行内存性能优化方面的各种实践。

vmo

Vmo 命令用来管理虚拟内存可调试的参数。例如如果我们发现空闲内存不足, 可以使用下面的命令增加 Minfree 和 Maxfree 参数:

清单 1. 使用 vmo 命令调整空闲的虚拟内存最小和最大值
 
				
 # vmo – o minfree=1024 – o maxfree=30070 
 Setting maxfree to 30070 
 Setting minfree to 1024 

注:-p 参数能够使修改永久生效,而且立即生效,不需要重启,下次重启设置仍然有效。例如 vmo -p – o minfree=1024 命令能够永久设置空闲的虚拟内存值为 1024

一般情况下,minfree 和 maxfree 的设定值可以通过下面的公式计算得到:

maxfree=minnum(memory/128,128)

minfree=maxfree/8

-a 参数能够显示当前所有的内存参数设置,之后系统管理员可以对其中的任何参数进行调整,在此必须说明的是:对内存参数的任何微小改动都有可能造成系统运行的不稳定,所以系统管理员做的任何修改,都必须非常慎重并且对可能造成的影响有所了解。 上文提到的两个关键参数 minfree 和 maxfree 也包含于下面的列表中。

清单 2. vmo 命令所能调整的内存参数
 
				
 # vmo -a 
       ams_loan_policy = n/a 
   force_relalias_lite = 0 
     kernel_heap_psize = 65536 
          lgpg_regions = 0 
             lgpg_size = 0 
       low_ps_handling = 1 
               maxfree = 30070 
               maxperm = 902102 
                maxpin = 845450 
               maxpin% = 80 
         memory_frames = 1048576 
         memplace_data = 2 
  memplace_mapped_file = 2 
 memplace_shm_anonymous = 2 
    memplace_shm_named = 2 
        memplace_stack = 2 
         memplace_text = 2 
 memplace_unmapped_file = 2 
               minfree = 1024 
               minperm = 30070 
              minperm% = 3 
             nokilluid = 0 
               npskill = 1024 
               npswarn = 4096 
             numpsblks = 131072 
       pinnable_frames = 868968 
   relalias_percentage = 0 
                 scrub = 0 
              v_pinshm = 0 
      vmm_default_pspa = 0 
 wlm_memlimit_nonpg = 1 

其中 maxperm, maxpin%, minperm, minpin% 值得我们特别的注意。 AIX 中, 文件型内存一般占用系统内存很少的一部分,大部分的内存被用来做计算型内存,其中一个主要的应用为 oracle SGA,所使用的内存为 pinned memory. 我们通常希望把 oracle SGA 保持在内存内,同时需要将文件系统缓存比例控制到一定范围内。 这时我们根据系统内存的大小,调整 maxpin%,maxperm,minpin%,minperm 的值。 minperm – 文件型内存最小值 minpin - 计算型内存最小值 minpin% - 计算型内存占总的系统内存百分比的最小值 maxperm – 文件型内存最大值 maxpin - 计算型内存最大值 maxpin% - 计算型内存占总的系统内存百分比的最大值

计算型内存和文件型内存的调整需要遵循下面的一些简单原则:

  1. 计算型内存和文件型内存所占系统内存百分比之和要小于 100%。
  2. 计算型内存的设置要合理,留出足够的空间给操作系统。 原因在于操作系统同样会占用一部分计算型内存,系统资源紧张时,操作系统会抢占应用程序所占计算型内存,影响程序的正确运行。
  3. 数据库服务器上,文件型内存不需要太多的空间。 通常我们会遇到的 paging space 占用率过高就有可能设置了过高的文件型内存。

进程空间内存监控命令

系统管理员有时需要对某个特定的进程进行跟踪调试,这时就需要一些命令能够动态的显示每个进程内存占用情况的实时信息。ps 是我们经常使用到的能够解决这方面问题的命令。事实上,这个命令的使用非常简单,但是得到的数据非常有效。

ps

几乎所有的 Unix/Linux 分发版都包含了这一工具,ps 提供的简洁而有效的信息能够允许系统管理员快速地对性能问题进行故障排除,不足之处就是其并不适合用于进行历史趋势研究与分析。 ps 一般用来查看系统中运行的进程,事实上,ps 命令同样可以帮助管理员对可能的内存瓶颈进行故障排除。

下面我们使用 ps 显示系统中每个活动进程的内存使用情况

清单 3. ps 命令输出当前内存状况
 
				
 # ps aux 
 USER PID %CPU %MEM SZ RSS TTY STAT STIME TIME COMMAND 
 root      53274 10.7  0.0  384  384      - A    03:17:33 453:29 wait 
 root       8196 10.7  0.0  384  384      - A    03:17:33 453:28 wait 
 root      49176 10.7  0.0  384  384      - A    03:17:33 453:20 wait 
 root      57372 10.7  0.0  384  384      - A    03:17:33 453:06 wait 

其中 rss 标示每个进程的实际内存使用量,这是我们需要重点查看的属性,代表着这个进程真正占用内存的多少。通过观察 rss 的数据信息,我们能够清楚的获得此进程的内存使用变化情况。

在极端情况下,系统管理员可以通过 kill 命令关闭某些内存占用率过高的进程来确保系统的正常运行。

同时我们也可以通过观察 rss 段的数据信息来检查进程存不存在内存泄漏现象。

系统内存监控命令

系统管理员除了需要对特定的进程内存占用情况跟踪观察外,更多的时候需要监控整个系统的内存使用信息。 Vmstat 和 svmon 能够帮助我们轻易的获得这方面的数据。

vmstat

vmstat(Virtual Memory Statistics) 命令能够帮助我们监控内核进程,虚拟内存,磁盘和处理器统计信息。 它是对系统的整体情况进行统计,不足之处就是无法对某个特定进程做分析。 Vmstat 的输出可以是以百分比表示的平均值,也可以是其统计的总和。

如果没有指定任何的参数,vmstat 将会输出系统从开机启动之后所有的虚拟内存活动。

我们经常使用类似 vmstat 5 5 的命令参数,代表着表示在 5 秒时间做 5 次采样。

清单 4. vmstat5 5 命令监控内存资源使用状况
 
				
 System Configuration: lcpu=4 mem=1024MB 

 kthr    memory              page              faults        cpu 
 ----- ----------- ------------------------ ------------ ----------- 
 r  b   avm   fre  re  pi  po  fr   sr  cy  in   sy  cs us sy id wa 
 0  0 208817 44828   0   0   0   0    0   0   3   60 220  0  0 99  0 
 0  0 208817 44828   0   0   0   0    0   0   2   27 225  0  0 99  0 
 0  0 208817 44828   0   0   0   0    0   0   4   29 219  0  0 99  0 

下面将对输出的结果中涉及到的内存管理相关字段进行说明:

memory:物理内存和虚拟内存的使用信息。如果虚拟内存被访问,那么将被认为是活动的。.

  • avm 活动的虚拟内存页面
  • fre 空闲内存列表的大小。注:很大一部分的实际内存都被用来作为文件系统的缓存用来加快应用程序的运行速度,所以空闲内存大小一般保持在很小的数值。

page:缺页异常和分页活动信息。此数值是间隔时间内的平均值,以秒为单位。

  • re 页面调度输入 / 输出列表
  • pi 从页面空间输入的页面
  • po 写入页面空间的页面
  • fr 释放的页面
  • sr 通过页面替换算法扫描页面的频率
  • cy 页面替换算法运行的时钟周期

内存的瓶颈问题我们可以通过 sr( 页面扫描频率 ) 来观察,如果扫描频率过高,始终维持高于 200 页说明存在内存瓶颈,同样的道理如果 page 项中的 pi( 调入的页面数 ) 和 po( 调出的页面数 ) 不为 0,说明系统必须经常性被动的通过页面的调入调出程序来维持系统的稳定运行,表明也有可能存在内存瓶颈。解决的方法可以通过简单的增加内存或者优化设计应用程序来减少对内存的使用率。

svmon

svmon 命令提供了一个更加深入的内存使用情况的分析,比起 vmstat 和 ps 命令,它带有更多的信息量。-i 选项能够间隔性的捕获一个内存状态的快照。

svmon 命令可以生成 9 种不同的报告结果,这里我们选用比较有代表性的带 -G 标志来监视内存全局使用情况。

清单 5. svmon 命令显示当前内存全局使用状况
 
				
 # svmon -G 
               size       inuse        free         pin     virtual 
 memory       262144      208128       54016       72891      163644 
 pg space     131072        1912 

               work        pers        clnt       other 
 pin           62497           0           0       10394 
 in use       163644           0       44484 

 PageSize   PoolSize       inuse        pgsp         pin     virtual 
 s    4 KB         -      128032        1912       24667       83548 
 m   64 KB         -        5006           0        3014        5006 
  • size 标示了实际内存的页面数
  • inuse 正在使用中的页面数
  • free 空闲的页面数
  • pin 物理内存中固定的页面数
  • virtual 虚拟内存使用的页面数

这里 svmon 只是提供了更加精确的结果,具体的内存调试优化可以参照以上 vmo, ps 和 svmstat 命令中所涉及到的方法。

Linux 内存管理与监控

Linux 系统内存监控命令

Linux 同样具有众多与内存管理相关的命令,可以帮助我们快速获得内存使用信息。 如 vmstat,ps,AIX 中我们已经做了介绍,在此不再赘述。 free 是 Linux 系统所具有的十分小巧简介的命令,这也是 Linux 上常用的查看内存的方式。

Free

与 AIX 系统中的 svnmon 命令类似,free 提供了内存全局使用情况。

清单 6. free 命令显示当前内存使用信息
 
				
 # free 
             total       used       free     shared    buffers     cached 
 Mem:       4166976    4063552     103424          0     875712    2694592 
 -/+ buffers/cache:     493248    3673728 
 Swap:      1052096        768    1051328 

下面是对各个输出字段的详细说明

  • total 总计物理内存的大小
  • used 已经使用的内存大小
  • free 空闲的内存大小
  • shared 多个进程共享的内存大小
  • buffers 块设备缓存的大小
  • cached 页面缓存的大小

free 命令所提供的数据不如 vmstat 所得到的详细,但是能够提供给我们最初和最直接的参考,指明我们需要仔细检查的方向,比如如果 shared memory 数据过大,我们就能很容易发现有些程序请求分配了过多的共享内存池,配合其他的管理命令,找到具体的某个进程消耗了过多的共享内存,从而解决问题。

内存监控自动化实现

合理的利用以上介绍的众多内存管理工具,系统管理员可以自己编写一些脚本自动化的监控内存使用情况,记录内存使用信息,设置警戒点,甚至阻止异常程序的内存申请行为,将系统从灾难中恢复过来。

下面是一个内存监控自动化脚本实现的例子 MemMonitor.perl。 这个脚本在使用内存达到或超过实际内存的 75% 的时候会打印出内存不足的警告。 在使用内存达到或超过实际内存的 90% 的时候,将打印出内存即将用尽的警告,并且关掉当前占用内存最高的进程。

同时我们通过将此脚本添加到 cron 服务中来实现内存的监控自动化。

脚本在 AIX5.3 和 SLES11 上测试通过。

清单 7. MemMonitor.perl
 
				
 #!/usr/bin/perl 
 use strict; 

 # 打印此脚本使用信息和输出说明。

 ################################################################ 
 # Output the usage of this perl script 
 ################################################################ 
 sub usage 
 { 
    print "memmonitor: Monitor system memory usage\n"; 
    print "1. if used memory is more than 75% of total memory, memmonitor\n"; 
    print "will output one warning message per minites.\n"; 
    print "2. if used memory is more than 90% of total momory, memmonitor\n"; 
    print "will kill the processes that occupied the most memory untill\n"; 
    print "used memory is less than 75% of total memory.\n\n"; 

    return 0; 
 } 

 usage 

 my $total_mem; 
 my $used_mem; 
 my $next_line = 0; 
 my @rc; 
 my $rate; 

 # $total_mem 和 $used_mem 变量分别代表了总计实际内存大小和已经使用的内存大小
 rc = `vmstat`; 
 foreach ( @rc ) { 
    if ( $next_line ) { 
      my @value = split /\s+/, $_; 
         $used_mem = @value[3] * 4; 
         $next_line = 0; 
         last; 
     } elsif ( /^.*mem=(\d+)MB$/ ) { 
         $total_mem = $1 * 1024; 
     } elsif ( /^.*avm.*$/ ) { 
         $next_line = 1; 
     } 
 } 

 # 这段代码使用了 vmstat 命令得到系统内存状态信息,并对结果进行逐行解析,得到各个字段的数据。

 if ( $total_mem ) { 
    $rate = $used_mem / $total_mem; 
 } 

 # 计算得到了当前全局内存使用率

 if ( $rate > 0.75 ) { 
    print "Warning: Memory is not enough\n"; 
 } 

 # 如果内存使用率大于 0.75, 将打印出警告信息。

 if ( $rate > 0.9 ) { 
    my $line_count = 0; 
    my @output = `ps aux | head -1;ps aux | sort -rn +5`; 
    foreach ( @output ) { 
        if ( $line_count ) { 
            my @killed_process = split /\s+/,$_; 
            print "Warning: Out of memory. Kill process: @killed_process[1]\n"; 
            # 发送警告信息给 root 用户,保存程序运行记录。
`echo "Process @killed_process[1] has been killed because of unlimited memory \
allocation" | mail -s "Out of memory" root` 

            `kill -11 @killed_process[1]`; 
            last; 
        } 
        $line_count = $line_count + 1; 
    } 

 # 如果内存使用率大于 0.9,脚本将调用 ps 命令并且找出内存使用率最高的进程,打印出将要杀掉进程的警告信息,
 #杀掉内存使用率最高的进程。 此过程将循环进行知道内存占用率低于 0.9 
 } 

清单 8. root 用户警告邮件内容
 
				
 From test@test.ibm.com  Tue July 31 13:01:12 2009 
 X-Original-To: root 
 Delivered-To: root@test.ibm.com 
 Date: Tue, 31 July 2009 13:01:11 -0400 
 To: root@test.ibm.com 
 Subject: Out of memory 
 User-Agent: Heirloom mailx 12.2 01/07/07 
 MIME-Version: 1.0 
 Content-Type: text/plain; charset=us-ascii 
 Content-Transfer-Encoding: 7bit 
 From: test@test.ibm.com

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

 Process 10482 has been killed because of unlimited memory allocation 

上面的脚本 MemMonitor.perl 实现了自动监控内存使用率,并对内存占用率比较高的时候分别作了处理,能够保障内存子系统的稳定运行。 下面我们将借助系统的 cron 服务每间隔设定的一段时间自动调用上面的脚本,实现内存监控管理的完全自动化。

使用命令“crontab – e”编辑 crontab,添加一条自动运行脚本 MemMonitor.perl 的项目:

清单 9. 添加为 cron 服务
 
				
 */2 * * * *  /tmp/MemMonitor.perl 2>&1 >> /tmp/memmonitor.log 

此时 MemMonitor.per 将被每两分钟自动执行一次,并将输出结果保存在 /tmp/memmonitor.log 中。

总结

本文详细介绍了 Unix/Linux 上常用的内存管理与监控的命令,并通过编写脚本实例应用内存管理的命令,实现了内存管理的自动化,当内存使用率过高的时候,给出警告信息,通过关闭内存占用率高的进程来确保了系统全局的稳定运行,并对其中所做的操作做了日志记录,方便了系统管理员监测并调试系统内存故障。

参考资料

学习
  • 本系列文章主要关注于实现 Unix/Linux 系统上的管理自动化,让读者了解到脚本语言以及相关的工具可以让日常的管理工作变得更加轻松。
  • OpenSSH 组织的官方网站: 从这里可以找到 openSSH 相关的资料。
  • Expect.pm 的使用手册:介绍了 Expect 的 Perl 语言接口。
  • EXPECT 的主页:从这里可以找到几乎所有关于 EXPECT 的资料,包括文档、FAQ、Wiki 和有用的链接。
  • Expect 超出预期:一种不为人知但功能强大的流行工具,文章介绍了 Expect 的基本功能。
  • IBM Publication:《命令参考大全,卷 5:s - u 》:AIX 6.1 信息中心文档,系统管理类。
  • 有关 Perl 信息及其相关资源,请查看 Perl.com
  • Programming Perl Third Edition(Larry Wall、Tom Christiansen 和 Jon Orwant 著;O'Reilly & Associates,2000)是当今最好的 Perl 指南,现在已经更新到 5.005 和 5.6.0。
  • Perl Cookbook(Tom Christiansen 和 Nathan Torkington 著;O'Reilly & Associates,1998)是关于所有 Perl 问题的权威性入门书籍。
  • AIX and Unix 专区:developerWorks 的“AIX and Unix 专区”提供了大量与 AIX 系统管理的所有方面相关的信息,您可以利用它们来扩展自己的 Unix 技能。
  • AIX and Unix 新手入门:访问“AIX and Unix 新手入门”页面可了解更多关于 AIX 和 Unix 的内容。
  • AIX and Unix 专题汇总:AIX and Unix 专区已经为您推出了很多的技术专题,为您总结了很多热门的知识点。我们在后面还会继续推出很多相关的热门专题给您,为了方便您的访问,我们在这里为您把本专区的所有专题进行汇总,让您更方便的找到您需要的内容。
  • developerWorks 技术活动 网络广播:随时关注 developerWorks 技术活动和网络广播。
获得产品和技术
  • IBM 试用软件:使用可从 developerWorks 直接下载的软件构建您的下一个开发项目。
讨论
火龙果软件/UML软件工程组织致力于提高您的软件工程实践能力,我们不断地吸取业界的宝贵经验,向您提供经过数百家企业验证的有效的工程技术实践经验,同时关注最新的理论进展,帮助您“领跑您所在行业的软件世界”。

资源网站: UML软件工程组织