設置 ulimit -v 是否足以避免記憶體洩漏
我們有一個程序在最近幾週發生了一次記憶體洩漏,導致它消耗了我們 RHEL 7 機器上的所有記憶體
我們現在希望對此設置限制,使其永遠不會超過一定數量
我們使用 ulimit -v 設置來設置這個數量(因為 -m 設置不起作用)
因此,我想知道這是否足夠,或者我們是否還需要一種方法來限制物理記憶體?如果是這樣,最好的方法是什麼?
如果虛擬記憶體總是隨著物理記憶體增長,那麼 -v 本身就足夠了
關於如何
ulimit
工作的一些描述:
ulimit
有處理setrlimit
和getrlimit
系統呼叫。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)的呼叫。
madvice
syscall 只是對核心的建議,核心可能會忽略此建議。甚至有關編寫以下內容bash
的手冊頁:ulimit
-m 最大駐留集大小**(許多系統不遵守此限制)**
這就是為什麼
-m
不起作用的原因。關於
-v
選項:我設置了 1024 kb 的虛擬記憶體:
$ ulimit -v 1024
在另一個控制台中:
$ strace -p <my_bash_pid> . . . 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 並包含程序指令。
- 數據段由以下控制:
brk
syscall 調整程序的數據段(虛擬記憶體的一部分)的大小。
mmap
系統呼叫將文件或設備映射到程序的虛擬記憶體。許多程序通過呼叫 C 庫 (
malloc
) 中的標準函式來分配記憶體(直接或間接),該函式從堆(數據段的一部分)分配記憶體。通過呼叫syscallmalloc
調整數據段的大小。brk
- 堆棧儲存函式變數(變數在從堆棧分配期間佔用記憶體)。
因此,這就是該
-v
選項適合您的原因。如果
-v
對你的任務來說足夠了,那麼就沒有理由做其他事情了,這就足夠了。如果您想控制大量特定的程序記憶體功能(記憶體壓力、交換使用、RSS 限制、OOM 等),我建議您使用cgroups 記憶體功能。
如果您的應用程序是一個服務,我建議您使用systemd 切片功能,因為它可以最方便地控制和限制
cgroups
由systemd
.