Unix/Linux 系統自動化管理: 記憶體管理篇

beatony發表於2010-05-19

Unix/Linux 系統自動化管理: 記憶體管理篇
 
本文是 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% - 計算型記憶體佔總的系統記憶體百分比的最大值

計算型記憶體和檔案型記憶體的調整需要遵循下面的一些簡單原則:

計算型記憶體和檔案型記憶體所佔系統記憶體百分比之和要小於 100%。
計算型記憶體的設定要合理,留出足夠的空間給作業系統。 原因在於作業系統同樣會佔用一部分計算型記憶體,系統資源緊張時,作業系統會搶佔應用程式所佔計算型記憶體,影響程式的正確執行。
資料庫伺服器上,檔案型記憶體不需要太多的空間。 通常我們會遇到的 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   Tue July 31 13:01:12 2009
 X-Original-To: root
 Delivered-To:
 Date: Tue, 31 July 2009 13:01:11 -0400
 To:
 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:

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

 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 上常用的記憶體管理與監控的命令,並透過編寫指令碼例項應用記憶體管理的命令,實現了記憶體管理的自動化,當記憶體使用率過高的時候,給出警告資訊,透過關閉記憶體佔用率高的程式來確保了系統全域性的穩定執行,並對其中所做的操作做了日誌記錄,方便了系統管理員監測並除錯系統記憶體故障。
 
 


 
 

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/22578826/viewspace-663111/,如需轉載,請註明出處,否則將追究法律責任。

相關文章