これを制限するもう 1 つの方法は、Linux のコントロール グループを使用することです。これは、プロセス (またはプロセスのグループ) の物理メモリの割り当てを、仮想メモリとは別に制限したい場合に特に便利です。例:
cgcreate -g memory:myGroup
echo 500M > /sys/fs/cgroup/memory/myGroup/memory.limit_in_bytes
echo 5G > /sys/fs/cgroup/memory/myGroup/memory.memsw.limit_in_bytes
myGroup
という名前のコントロール グループを作成します 、 myGroup
の下で実行されるプロセスのセットを制限します memory.limit_in_bytes
で最大 500 MB の物理メモリ memory.memsw.limit_in_bytes
と合わせて最大 5000 MB の物理メモリとスワップ メモリ .これらのオプションの詳細については、https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/6/html/resource_management_guide/sec-memory を参照してください。
制御グループの下でプロセスを実行するには:
cgexec -g memory:myGroup pdftoppm
最新の Ubuntu ディストリビューションでは、この例では cgroup-bin
をインストールする必要があることに注意してください。 パッケージと /etc/default/grub
の編集 GRUB_CMDLINE_LINUX_DEFAULT
を変更するには へ:
GRUB_CMDLINE_LINUX_DEFAULT="cgroup_enable=memory swapaccount=1"
そして sudo update-grub
を実行します 再起動して、新しいカーネル ブート パラメータで起動します。
プロセスが、最も多くのメモリを消費する子プロセスを生成しない場合は、setrlimit
を使用できます。 関数。そのためのより一般的なユーザー インターフェイスは ulimit
を使用しています シェルのコマンド:
$ ulimit -Sv 500000 # Set ~500 mb limit
$ pdftoppm ...
これは、呼び出されたプロセスが他のプロセスと共有するメモリ、およびマップされているが予約されていないメモリ (たとえば、Java の大きなヒープ) を考慮して、プロセスの「仮想」メモリのみを制限します。それでも、仮想メモリは、非常に大きくなるプロセスの最も近い近似であるため、前述のエラーは重要ではありません.
プログラムが子を生成し、メモリを割り当てるのが子である場合は、より複雑になるため、制御下でプロセスを実行する補助スクリプトを作成する必要があります。その理由と方法をブログに書きました。
ulimit にはいくつかの問題があります。このトピックに関する有用な読み物は次のとおりです:Linux でのプログラムの時間とメモリ消費の制限。これはタイムアウト ツールにつながり、プロセス (およびそのフォーク) を時間またはメモリ消費によってケージに入れることができます。
タイムアウト ツールには、Perl 5 以降と /proc
が必要です。 ファイルシステムがマウントされました。その後、ツールをコピーします。 /usr/local/bin
そのように:
curl https://raw.githubusercontent.com/pshved/timeout/master/timeout | \
sudo tee /usr/local/bin/timeout && sudo chmod 755 /usr/local/bin/timeout
その後、質問のように、メモリ消費によってプロセスを「ケージ」に入れることができます:
timeout -m 500 pdftoppm Sample.pdf
または、 -t <seconds>
を使用することもできます と -x <hertz>
時間または CPU の制約によってプロセスをそれぞれ制限します。
このツールが機能する方法は、生成されたプロセスが設定された境界をオーバーサブスクライブしていないかどうかを 1 秒あたり複数回チェックすることです。これは、プロセスが潜在的にできる小さなウィンドウが実際にあることを意味します。 タイムアウトが通知されてプロセスが強制終了される前にオーバーサブスクライブします。
したがって、より正しいアプローチには cgroups が含まれる可能性がありますが、Docker や runC を使用する場合でも、セットアップがはるかに複雑になります。これらは cgroups に関するよりユーザーフレンドリーな抽象化を提供します。