여러 개의 메모리 집약적 프로그램(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
로 설정 하면 오버커밋이 활성화되고 프로그램은 실제로 사용 가능한 것보다 더 많은 메모리를 할당할 수 있습니다.0
1
그러나 프로그램이 자신이 할당한 메모리를 사용하려고 하지만 커널이 실제로 이를 만족시킬 메모리가 충분하지 않다는 것을 발견하면 일부 메모리를 다시 가져와야 합니다. 먼저 캐시 플러시 등 다양한 메모리 정리 작업을 시도하지만, 이것이 충분하지 않으면 프로세스를 종료합니다. 이 종료는 OOM-Killer에 의해 수행됩니다. OOM-Killer는 시스템을 조사하여 어떤 프로그램이 어떤 메모리를 사용하고 있는지, 얼마나 오래 실행되었는지, 누가 실행하고 있는지, 그리고 어떤 프로그램이 종료되는지를 결정하는 기타 여러 요인을 확인합니다.
프로세스가 종료된 후에는 사용 중이던 메모리가 해제되고, 방금 메모리 부족 상태를 일으킨 프로그램이 이제 필요한 메모리를 갖게 됩니다.
그러나 이 모드에서도 프로그램은 여전히 할당 요청을 거부할 수 있습니다. overcommit_memory
is 인 경우 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