Linux

設置 ulimit -v 是否足以避免記憶體洩漏

  • May 24, 2018

我們有一個程序在最近幾週發生了一次記憶體洩漏,導致它消耗了我們 RHEL 7 機器上的所有記憶體

我們現在希望對此設置限制,使其永遠不會超過一定數量

我們使用 ulimit -v 設置來設置這個數量(因為 -m 設置不起作用)

因此,我想知道這是否足夠,或者我們是否還需要一種方法來限制物理記憶體?如果是這樣,最好的方法是什麼?

如果虛擬記憶體總是隨著物理記憶體增長,那麼 -v 本身就足夠了

關於如何ulimit工作的一些描述:

ulimit有處理setrlimitgetrlimit系統呼叫。strace通過bash 程序的 -ing很容易確保(ulimit是 的組件bash)。我設置了 1024kb 的max memory size

$ ulimit -m 1024

在另一個控制台中:

$ strace -p <my_bash_pid>
. . .
getrlimit(RLIMIT_RSS, {rlim_cur=1024*1024, rlim_max=1024*1024}) = 0
setrlimit(RLIMIT_RSS, {rlim_cur=1024*1024, rlim_max=1024*1024}) = 0
. . . 

setrlimit手冊頁寫下關於RLIMIT_RSS

RLIMIT_RSS指定程序駐留集的限制(以頁為單位)(駐留在 RAM 中的虛擬頁數)。此限制僅在Linux 2.4.x、x < 30中有效,並且僅影響對 指定 MADV_WILLNEED的madvise(2)的呼叫。

madvicesyscall 只是對核心的建議,核心可能會忽略此建議。甚至有關編寫以下內容bash的手冊頁:ulimit

-m 最大駐留集大小**(許多系統不遵守此限制)**

這就是為什麼-m不起作用的原因。

關於-v選項:

我設置了 1024 kb 的虛擬記憶體:

$ ulimit -v 1024

在另一個控制台中:

$ strace -p &lt;my_bash_pid&gt;
. . .
getrlimit(RLIMIT_AS, {rlim_cur=RLIM64_INFINITY, rlim_max=RLIM64_INFINITY}) = 0
setrlimit(RLIMIT_AS, {rlim_cur=1024*1024, rlim_max=1024*1024}) = 0
. . .

setrlimit手冊頁寫下關於RLIMIT_AS

RLIMIT_AS程序的虛擬記憶體(地址空間)的最大大小,以字節為單位。此限制會影響對brk(2)、**mmap(2)**和 **mremap(2)**的呼叫,超過此限制時會失敗並返回錯誤 ENOMEM。自動堆棧擴展也會失敗(如果沒有通過 sigaltstack(2) 提供可用的備用堆棧,則會生成一個終止程序的 SIGSEGV)。由於該值為 long,因此在具有 32 位長度的機器上,此限制最多為 2 GiB,或者此資源是無限的。

程序由 3 個段(數據、程式碼、堆棧)組成,組成虛擬程序儲存空間。

  • 程式碼段是 const 並包含程序指令。
  • 數據段由以下控制:

brksyscall 調整程序的數據段(虛擬記憶體的一部分)的大小。

mmap系統呼叫將文件或設備映射到程序的虛擬記憶體。

許多程序通過呼叫 C 庫 ( malloc) 中的標準函式來分配記憶體(直接或間接),該函式從(數據段的一部分)分配記憶體。通過呼叫syscallmalloc調整數據段的大小。brk

  • 堆棧儲存函式變數(變數在從堆棧分配期間佔用記憶體)。

因此,這就是該-v選項適合您的原因。

如果-v對你的任務來說足夠了,那麼就沒有理由做其他事情了,這就足夠了。


如果您想控制大量特定的程序記憶體功能(記憶體壓力、交換使用、RSS 限制、OOM 等),我建議您使用cgroups 記憶體功能。

如果您的應用程序是一個服務,我建議您使用systemd 切片功能,因為它可以最方便地控制和限制cgroupssystemd.

引用自:https://unix.stackexchange.com/questions/438986