プロセスとその子の合計リソース(メモリ)を制限する方法


16

単一のプロセスのリソースを制限することについては、多くの質問と回答があります。たとえば、RLIMIT_ASを使用して、などのVIRTと見なすことができるプロセスによって割り当てられる最大メモリを制限できますtop。もっとここで例えばトピックに関する特定のプロセスがUNIXで使用できるメモリの量を制限する方法はありますか?

setrlimit(2) ドキュメントは言う:

fork(2)を介して作成された子プロセスは、その親のリソース制限を継承します。リソース制限はexecve(2)全体で保持されます。

次のように理解する必要があります。

プロセスのRLIMIT_ASが2GBなどの場合、2GBを超えるメモリを割り当てることはできません。子が生成されると、2GBのアドレススペース制限が子に渡されますが、カウントは0から始まります。2つのプロセスを一緒にすると、最大4GBのメモリを使用できます。

しかし、プロセスのツリー全体によって割り当てられたメモリの合計を制約する便利な方法は何でしょうか?



7
cgroupsを見てみましょう。
slm

@slmありがとう!cgroupsのような音は試してみてください。これまでの唯一の有効なソリューション(PSを使用してメモリを加算し、制限を超えた場合に親プロセスを強制終了するwayい方法を除く)は、何らかの形式のコンテナ(lxcなど)を使用することです。
jpe 14年

ええ-私が知っているツールはグループではなく、単一のプロセスですが、LXCやDockerなどのVMテクノロジーでcgroupがどのように機能するかを考えると、あなたが望むことを期待しています。
slm

1
Linuxの場合は、親PIDを独自の名前空間に入れて、それとそのすべての子をそのように制御します。その概念に対する紹介的な答えは次のとおり
a

回答:


8

これがあなたの質問に答えるかどうかはわかりませんが、あなたが探しているものを正確に実行すると主張するこのperlスクリプトを見つけました。このスクリプトは、プロセスとその子のリソース使用を起動してチェックすることにより、制限を強制する独自のシステムを実装します。十分に文書化され説明されているようで、最近更新されました。

slmがコメントで述べたように、これにはcgroupsも使用できます。Linuxを使用している場合は、cgroupを管理するためのユーティリティをインストールする必要がありますlibcgroups

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

$USERユーザーであることを確認してください。

これで、ユーザーはのcgroupメモリ設定にアクセスできるようになります/sys/fs/cgroup/memory/myGroup

次に、これを行うことにより、たとえば500 MBに制限を設定できます。

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

Vimを実行します。

cgexec -g memory:myGroup vim

vimプロセスとそのすべての子は、500 MBのRAMの使用に制限されるはずです。ただし、この制限はRAMにのみ適用され、スワップには適用されないと思います。プロセスが制限に達すると、スワッピングが開始されます。これを回避できるかどうかはわかりませんが、cgroupを使用してスワップの使用を制限する方法は見つかりません。


提案されたソリューションは、プロセスのツリーの常駐セットサイズを制限することを可能にします。動作はRLIMIT_ASとは異なるようです。制限よりも多くのメモリをmallocすることは可能ですが、実際にそれ以上を使用することはできないようです。
jpe 14年

デフォルトでは、cgroupのメモリ制限は(およそ)物理RAMの使用にのみ適用されます。スワップアカウンティングを有効にするカーネルオプション(CONFIG_MEMCG_SWAP)があります。詳細については、カーネルのドキュメントを参照してください。
ソーレンLøvborg15年

1
フェドーラ、sudo yum install libcgroup-tools
-jozxyqk

2

Ubuntuで使用されるcgmanagerを使用して、これを行うスクリプトを作成しました。1つの利点は、これにはルートアクセスが必要ないことです。cgroup管理は少しディストリビューション固有なので、systemd cgroup管理を使用するディストリビューションでこれが機能するかどうかはわかりません。

#!/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

使用法:limitmemパスとして保存し、実行可能にします。次に、例えばを実行しlimitmem 1G command...ます。これにより、実際に使用されるメモリが制限されます。それに達すると、OOMキラーはプロセスまたはその子の1つを殺しますが、このコマンドとは関係のないランダムなものは殺しません。


短いcgmガイドをありがとう、それは役に立ちました
ヴィタリーイザエフ

1

/unix//a/536046/4319

systemdベースのディストリビューションでは、systemd-runを介して間接的にcgroupsを使用することもできます。たとえばpdftoppm、RAMを500Mに制限する場合、次を使用します。

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

...

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.