메모리 오버커밋 = 2

메모리 오버커밋 = 2

여러 개의 메모리 집약적 프로그램(2~5GB)을 연속적으로 실행하는 명령이 포함된 셸 스크립트를 실행하고 있습니다. 스크립트의 진행 상황을 확인하기 위해 다시 돌아갔을 때 Killed터미널에 보고된 대로 일부 프로세스가 이라는 사실에 놀랐습니다 . 프로그램이 나중에 시작되기 전에 여러 프로그램이 완료되었지만 Killed그 이후의 모든 프로그램은 분할 오류로 인해 실패합니다(이는 내 코드의 버그로 인한 것일 수도 있고 아닐 수도 있습니다. 계속 읽어 보십시오).

제가 작업 중인 특정 클러스터의 사용 기록을 살펴본 결과 누군가가 동시에 여러 메모리 집약적 프로세스를 실행하기 시작했고 그렇게 함으로써 클러스터에서 사용할 수 있는 실제 메모리를 모두 사용했다는 사실을 발견했습니다. ). 내가 알 수 있는 바에 따르면, 이러한 메모리 집약적인 프로세스는 내 프로그램에 문제가 발생하기 시작한 것과 동시에 실행되기 시작했습니다.

메모리가 부족할 때 Linux가 내 프로그램을 종료할 수 있습니까? 나중에 발생한 분할 오류가 내 코드의 버그가 아니라 내 프로그램을 실행하는 데 사용할 수 있는 메모리 부족으로 인한 것일 수 있습니까?

답변1

그것은 할 수 있습니다.

Linux에서 발생할 수 있는 메모리 부족 상황에는 두 가지가 있습니다. sysctl vm.overcommit_memory( /proc/sys/vm/overcommit_memory) 의 값 에 따라 발생하는 상황이 달라집니다 .

요약:
커널은 "메모리 오버커밋"을 수행할 수 있습니다. 이는 커널이 실제로 시스템에 존재하는 것보다 더 많은 메모리를 프로그램에 할당하는 경우입니다. 이는 프로그램이 할당한 모든 메모리를 실제로 사용하지 않기를 바라면서 수행됩니다. 이는 매우 일반적인 상황이기 때문입니다.

메모리 오버커밋 = 2

overcommit_memory로 설정 하면 2커널은 오버커밋을 전혀 수행하지 않습니다. 반대로, 프로그램에 메모리가 할당되면 해당 메모리에 대한 액세스가 보장됩니다. 시스템에 할당 요청을 충족할 만큼 충분한 여유 메모리가 없으면 커널은 요청 실패를 반환합니다. 이 상황을 적절하게 처리하는 것은 프로그램에 달려 있습니다. 할당이 실제로 실패했지만 할당이 성공했는지 여부를 확인하지 않으면 응용 프로그램에서 종종 segfault가 발생합니다.

segfault의 경우 다음 출력에서 ​​다음과 같은 줄을 찾아야 합니다 dmesg.

[1962.987529] myapp[3303]: segfault at 0 ip 00400559 sp 5bc7b1b0 error 6 in myapp[400000+1000]

이는 at 0응용 프로그램이 초기화되지 않은 포인터에 액세스하려고 시도하고 있음을 의미하며, 이는 실패한 메모리 할당 호출의 결과일 수 있습니다(그러나 이것이 유일한 방법은 아닙니다).

과도한 메모리 사용량 = 0 및 1

또는 overcommit_memory로 설정 하면 오버커밋이 활성화되고 프로그램은 실제로 사용 가능한 것보다 더 많은 메모리를 할당할 수 있습니다.01

그러나 프로그램이 자신이 할당한 메모리를 사용하려고 하지만 커널이 실제로 이를 만족시킬 메모리가 충분하지 않다는 것을 발견하면 일부 메모리를 다시 가져와야 합니다. 먼저 캐시 플러시 등 다양한 메모리 정리 작업을 시도하지만, 이것이 충분하지 않으면 프로세스를 종료합니다. 이 종료는 OOM-Killer에 의해 수행됩니다. OOM-Killer는 시스템을 조사하여 어떤 프로그램이 어떤 메모리를 사용하고 있는지, 얼마나 오래 실행되었는지, 누가 실행하고 있는지, 그리고 어떤 프로그램이 종료되는지를 결정하는 기타 여러 요인을 확인합니다.

프로세스가 종료된 후에는 사용 중이던 메모리가 해제되고, 방금 메모리 부족 상태를 일으킨 프로그램이 이제 필요한 메모리를 갖게 됩니다.

그러나 이 모드에서도 프로그램은 여전히 ​​할당 요청을 거부할 수 있습니다. overcommit_memoryis 인 경우 0커널은 할당 요청 거부를 시작해야 하는 시점에 대해 최선의 추측을 시도합니다. 로 설정된 경우 1요청을 거부해야 하는 시기를 결정하기 위해 어떤 결정을 사용하는지 잘 모르겠지만 매우 큰 요청을 거부할 수 있습니다.

dmesg출력을 보고 다음과 같은 메시지를 찾아보면 OOM-Killer가 관련되어 있는지 확인할 수 있습니다 .

[11686.043641] Out of memory: Kill process 2603 (flasherav) score 761 or sacrifice child
[11686.043647] Killed process 2603 (flasherav) total-vm:1498536kB, anon-rss:721784kB, file-rss:4228kB

답변2

사실, 어떤 방식으로 보든, 즉 시스템의 메모리 관리자로 인해 프로세스가 차단되고 있든, 아니면 다른 이유로든, 그것은 사실입니다.아직실수. 방금 메모리에서 처리한 모든 데이터는 어떻게 되나요? 저장해야합니다.

이는 Linux OOM 관리를 구성하는 가장 일반적인 방법 이지만 overcommit_memory=프로세스별로 조정할 수도 있습니다. 예를 들면 다음과 같습니다.

echo [-+][n] >/proc/$pid/oom_adj

위를 사용하면 -17메모리 부족 관리에서 해당 프로세스가 제외됩니다. 아마도 일반적으로 좋은 생각은 아닐 것입니다. 그러나 버그를 찾고 있다면 시도해 볼 가치가 있을 것입니다. 특히 그것이 OOM인지 알고 싶다면 더욱 그렇습니다.또는당신의 코드. 이 숫자를 적극적으로 늘리면 OOM 이벤트에서 프로세스가 종료될 가능성이 높아집니다. 이를 통해 메모리가 부족한 상황에서 코드의 탄력성을 더 향상시키고 필요할 때 정상적으로 종료할 수 있습니다.

각 프로세스의 OOM 핸들러의 현재 설정을 확인할 수 있습니다. 예를 들면 다음과 같습니다.

cat /proc/$pid/oom_score 

그렇지 않으면 자살할 수도 있습니다.

sysctl vm.panic_on_oom=1
sysctl kernel.panic=X

메모리가 부족하면 컴퓨터가 다시 시작됩니다. X위의 시간을 커널 패닉 후 다시 시작하기 전에 컴퓨터를 중지할 시간(초)으로 설정합니다 . 야생으로 가십시오.

어떤 이유로든 마음에 든다고 결정했다면 지속적으로 사용하세요.

echo "vm.panic_on_oom=1" >> /etc/sysctl.conf
echo "kernel.panic=X" >> /etc/sysctl.conf

관련 정보