Bir sürecin ve çocuklarının toplam kaynaklarını (hafızasını) sınırlama


16

Tek bir işlemin kaynaklarını kısıtlama konusunda birçok soru ve cevap vardır; örneğin, RLIMIT_AS, benzerlerinde VIRT olarak görülebilen bir işlem tarafından ayrılan maksimum belleği kısıtlamak için kullanılabilir top. Konu hakkında daha fazla bilgi Burada belirli bir işlemin Unix'te kullanabileceği bellek miktarını sınırlamanın bir yolu var mı?

setrlimit(2) belgeler diyor ki:

Fork (2) ile oluşturulan bir alt süreç, üst öğesinin kaynak sınırlarını devralır. Kaynak sınırları yürütme (2) boyunca korunur.

Aşağıdaki şekilde anlaşılmalıdır:

Bir işlemin RLIMIT_AS değeri 2GB ise, 2GB'den fazla bellek ayıramaz. Bir çocuk doğurduğunda, 2GB adres alanı sınırı çocuğa aktarılır, ancak sayım 0'dan başlar. 2 işlem birlikte 4GB'a kadar bellek alabilir.

Ancak, tüm süreçler ağacı tarafından ayrılan toplam bellek miktarını sınırlamanın yararlı yolu ne olabilir?



7
Gruplara bir göz atarım .
slm

@slm Teşekkürler! Krupiyeler gibi görünmesi gereken bir şey. Şimdiye kadar çalışan tek çözüm (PS kullanarak bellek toplamanın çirkin bir yolunun yanı sıra, sınırın üstünde ise ana işlemi öldürmenin yanı sıra) bir konteyner (lxc veya benzeri) kullanmaktır.
jpe

Evet - farkında olduğum araçlar bir grup yapmıyor, sadece tek işlemler yapıyor, ancak LXC ve Docker gibi VM teknolojilerinde cgroup'ların nasıl çalıştığı göz önüne alındığında, istediğini yapmasını beklerdim.
slm

1
Linux ise, üst PID'yi kendi ad alanına koyun ve onu ve tüm çocuklarını bu şekilde kontrol edin. İşte bu konsepte giriş niteliğinde bir cevap: unix.stackexchange.com/a/124194/52934
mikeserv

Yanıtlar:


8

Bu sorunuzu cevaplıyorsa emin değilim, ama tam olarak aradığınızı yaptığını iddia eden bu perl betiğini buldum . Komut dosyası, sürecin ve çocuklarının kaynak kullanımını uyandırarak ve kontrol ederek sınırları uygulamak için kendi sistemini uygular. İyi belgelenmiş ve açıklanmış gibi görünüyor ve yakın zamanda güncellendi.

Slm'nin yorumunda söylediği gibi, bunun için gruplar da kullanılabilir. Aramanız gereken Linux'ta olduğunuzu varsayarak, grupları yönetmek için yardımcı programları yüklemeniz gerekebilir libcgroups.

sudo cgcreate -t $USER:$USER -a $USER:$USER -g memory:myGroup

$USERKullanıcının olduğundan emin ol .

Ardından, kullanıcınızın içindeki grup belleği ayarlarına erişmesi gerekir /sys/fs/cgroup/memory/myGroup.

Daha sonra, bunu yaparak 500 MB diyelim.

echo 500000000 > /sys/fs/cgroup/memory/myGroup/memory.limit_in_bytes

Şimdi Vim'i çalıştıralım:

cgexec -g memory:myGroup vim

Vim işlemi ve tüm çocukları şimdi 500 MB RAM kullanmakla sınırlandırılmalıdır. Ancak , bu sınırın sadece RAM için geçerli olduğunu ve takas olmadığını düşünüyorum. İşlemler sınıra ulaştığında değişmeye başlarlar. Bunu aşabilirseniz emin değilim, cgroups kullanarak takas kullanımını sınırlamak için bir yol bulamıyorum.


Önerilen çözüm, bir süreç ağacının yerleşik set boyutunu sınırlamayı mümkün kılar. Davranış RLIMIT_AS'tan farklı gibi görünüyor: sınırdan daha fazla bellek ayırmak mümkündür, ancak aslında daha fazla kullanmak mümkün görünmemektedir.
jpe

Varsayılan olarak, grup belleği sınırı yalnızca (yaklaşık olarak) fiziksel RAM kullanımına uygulanır. Takas muhasebesini etkinleştirmek için bir çekirdek seçeneği (CONFIG_MEMCG_SWAP) vardır; ayrıntılar için çekirdek belgelerine bakın.
Søren Løvborg

1
sudo yum install libcgroup-tools
Fedora'da

2

Ubuntu'da kullanılan cgmanager kullanarak bunu yapan bir komut dosyası oluşturdum. Bunun bir avantajı, bunun root erişimi gerektirmemesidir. Cgroup yönetimi biraz distro özgü olduğunu unutmayın, bu yüzden bu sistemd cgroup yönetimi kullanan distros üzerinde çalışıp çalışmadığını bilmiyorum.

#!/bin/sh

set -eu

if [ "$#" -lt 2 ]
then
    echo Usage: `basename $0` "<limit> <command>..."
    exit 1
fi

limit="$1"
shift
cgname="limitmem_$$"
echo "limiting memory to $limit (cgroup $cgname) for command $@"

cgm create memory "$cgname" >/dev/null
cgm setvalue memory "$cgname" memory.limit_in_bytes "$limit" >/dev/null
# try also limiting swap usage, but this fails if the system has no swap
cgm setvalue memory "$cgname" memsw.limit_in_bytes "$limit" >/dev/null 2>&1 || true

# spawn subshell to run in the cgroup
set +e
(
set -e
cgm movepid memory "$cgname" `sh -c 'echo $PPID'` > /dev/null
exec "$@"
)
# grab exit code
exitcode=`echo $?`

set -e

echo -n "peak memory used: "
cgm getvalue memory "$cgname" memory.max_usage_in_bytes | tail -1 | cut -f2 -d\"

cgm remove memory "$cgname" >/dev/null
exit $exitcode

kullanım: yolunuzdaki gibi limitmemkaydedin ve çalıştırılabilir yapın. Sonra örn limitmem 1G command.... Bu aslında kullanılan belleği sınırlar. Buna ulaşılırsa, OOM katili süreci veya çocuklarından birini öldürür, ancak bu komutla ilgisi olmayan rastgele bir şey değil.


Kısa cgmrehber için teşekkürler , faydalı oldu
Vitaly Isaev

1

/unix//a/536046/4319 :

Herhangi bir systemd tabanlı dağıtımda sistem gruplarından dolaylı olarak cgroups kullanabilirsiniz. Örneğin pdftoppm, 500M RAM ile sınırlama durumunda şunları kullanın:

systemd-run --scope -p MemoryLimit=500M pdftoppm

...

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.