프로세스와 해당 자식의 총 리소스 (메모리)를 제한하는 방법


16

단일 프로세스의 리소스를 제한하는 방법에 대한 많은 질문과 답변이 있습니다. 예를 들어 RLIMIT_AS를 사용하여 프로세스에서 할당 한 최대 메모리를 제한하는 데 사용할 수 있습니다 top. 예를 들어 여기에서 더 많은 주제 유닉스에서 특정 프로세스가 사용할 수있는 메모리의 양을 제한하는 방법이 있습니까?

setrlimit(2) 문서는 말합니다 :

fork (2)를 통해 생성 된 자식 프로세스는 부모의 리소스 제한을 상속합니다. 리소스 제한은 execve (2)에서 유지됩니다.

다음과 같은 방식으로 이해해야합니다.

프로세스의 RLIMIT_AS가 2GB 인 경우 2GB보다 많은 메모리를 할당 할 수 없습니다. 자식이 생성되면 주소 공간 제한 2GB가 자식으로 전달되지만 계산은 0부터 시작합니다. 두 프로세스는 함께 최대 4GB의 메모리를 사용할 수 있습니다.

그러나 전체 프로세스 트리에 의해 할당 된 총 메모리 양을 제한하는 유용한 방법은 무엇입니까?



7
나는 cgroups를 살펴볼 것이다 .
slm

@slm 감사합니다! cgroups처럼 들리는 것이 좋습니다. 지금까지 유일하게 작동하는 솔루션 (PS를 사용하여 추억을 합산하고 한계를 초과하면 부모 프로세스를 종료하는 방법 제외)은 어떤 형태의 컨테이너 (lxc 등)를 사용하는 것입니다.
jpe

예-내가 알고있는 도구는 그룹을 수행하지 않고 단일 프로세스 만 수행하지만 cgroup이 LXC 및 Docker와 같은 VM 기술에서 작동하는 방식을 고려하면 원하는대로 수행 할 것으로 기대합니다.
slm

1
Linux 인 경우 부모 PID를 자체 네임 스페이스에 넣고 모든 자식을 그렇게 제어하십시오. 여기에 그 개념에 대한 소개 답변이 있습니다 : unix.stackexchange.com/a/124194/52934
mikeserv

답변:


8

이것이 귀하의 질문에 대한 답변인지 확실하지 않지만, 당신이 찾고있는 것을 정확하게 수행한다고 주장하는 이 펄 스크립트 를 발견 했습니다. 이 스크립트는 프로세스와 해당 자식의 리소스 사용을 깨우고 확인하여 제한을 적용하기위한 자체 시스템을 구현합니다. 잘 문서화되고 설명 된 것으로 보이며 최근에 업데이트되었습니다.

slm이 그의 의견에서 말했듯이 cgroups도 사용할 수 있습니다. Linux에 있다고 가정하고 cgroup 관리를위한 유틸리티를 설치해야 할 수도 있습니다 libcgroups.

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

$USER사용자 인지 확인하십시오 .

그러면 사용자는의 cgroup 메모리 설정에 액세스 할 수 있어야합니다 /sys/fs/cgroup/memory/myGroup.

그런 다음 다음을 수행하여 500MB로 제한을 설정할 수 있습니다.

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

이제 Vim을 실행 해 봅시다 :

cgexec -g memory:myGroup vim

vim 프로세스와 모든 하위 프로세스는 이제 500MB의 RAM 사용으로 제한됩니다. 그러나이 제한은 RAM에만 적용되며 스왑은 아니라고 생각합니다. 프로세스가 한계에 도달하면 스와핑이 시작됩니다. 이 문제를 해결할 수 있는지 잘 모르겠습니다 .cgroup을 사용하여 스왑 사용을 제한하는 방법을 찾을 수 없습니다.


제안 된 솔루션은 프로세스 트리의 상주 세트 크기를 제한 할 수있게합니다. 동작은 RLIMIT_AS와 다른 것 같습니다. 한계보다 많은 메모리를 사용할 수는 있지만 실제로 더 많이 사용할 수는 없습니다.
jpe

기본적으로 cgroup 메모리 제한은 물리적 RAM 사용 (대략)에만 적용됩니다. 스왑 계정을 활성화하는 커널 옵션 (CONFIG_MEMCG_SWAP)이 있습니다. 자세한 내용은 커널 문서 를 참조하십시오.
Søren Løvborg 2016 년

1
페도라에서sudo yum install libcgroup-tools
jozxyqk 11

2

우분투에서 사용되는 cgmanager를 사용 하여이 작업을 수행하는 스크립트를 만들었습니다. 한 가지 장점은 루트 액세스가 필요하지 않다는 것입니다. 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 킬러는 프로세스 또는 해당 하위 프로세스 중 하나를 종료하지만이 명령과 관련이없는 임의의 것은 아닙니다.


짧은 주셔서 감사합니다 cgm가이드, 그것은 유용했다
비탈리 Isaev

1

/unix//a/536046/4319 :

모든 시스템 기반 배포판에서 systemd-run을 통해 간접적으로 cgroup을 사용할 수도 있습니다. 예를 들어 pdftoppm500M의 RAM 으로 제한 하는 경우 다음을 사용하십시오.

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

...

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.