많은 메모리를 사용하지만 여전히 사용 가능한 스왑 공간보다 적은 경우 Linux 프로세스가 충돌하는 이유는 무엇입니까?

많은 메모리를 사용하지만 여전히 사용 가능한 스왑 공간보다 적은 경우 Linux 프로세스가 충돌하는 이유는 무엇입니까?

저는 Linux 5.15와 Ubuntu 22.04를 사용하고 있습니다.

많은 메모리를 사용하는 프로세스가 있습니다. 내 컴퓨터의 RAM보다 더 많은 메모리가 필요합니다. 처음 실행했을 때 OOM Killer에 의해 종료되었습니다. 제가 이해한 바는 시스템에 메모리가 부족하고 OOM Killer가 실행되어 프로세스가 종료된다는 것입니다. 이것은 의미가 있습니다. 나는 또한 이것이 일어난 일이라고 확신합니다. 살펴보니 dmesg모든 것이 거기에 있었습니다.

그래서 스왑 공간을 추가했습니다. 프로세스를 실행하는 데 시간이 오래 걸려도 상관없습니다. 자주 실행하지 않을 것입니다.

프로세스를 다시 실행합니다. 이번 런은 첫 번째 런보다 길었습니다. 전체 시스템이 매우 지연되며, 이는 시스템이 많은 스와핑을 수행할 때 발생합니다. 효과가 있는 것 같더니... 그러다가 죽었습니다. 프로세스가 종료될 뿐만 아니라 상위 셸 프로세스, 상위 Tmux 프로세스, Tmux 프로세스의 상위 셸 프로세스, 심지어 GNOME 터미널 프로세스도 종료됩니다.그것은부모! 그러나 살인 과정은 중단됩니다. 더 이상 부모가 죽지 않습니다.

처음에는 사용 가능한 스왑 공간이 여전히 많음에도 불구하고 OOM Killer가 다시 실행된 것으로 생각하고 GNOME 터미널 프로세스를 종료하기로 결정했습니다. 그런데 확인해 보니 dmesg새로운 journalctl -k건 없었습니다. OOM Killer가 실행되었다는 표시는 없습니다.

첫 번째 질문: 커널 링 버퍼에 아무것도 기록하지 않고 OOM Killer가 실행될 수 있는 상황이 있습니까?

나를 혼란스럽게 하는 것은 Linux 커널이 스와핑을 시작하는 것 같지만 어떻게든 충분히 스와핑하지 않거나 충분히 빠르게 스와핑하지 않는다는 것입니다... 등등.

그래서 나는 그것을 늘렸다 vm.swappiness. 이는 실제로 시스템 안정성에 영향을 주어서는 안 됩니다. 이는 단지 성능 최적화를 위한 손잡이일 뿐입니다. 커널 vm.swappiness로 설정된 경우에도 0해당 영역의 사용 가능한 메모리가 임계 임계값 아래로 떨어지면 커널은 여전히 ​​스와핑을 시작해야 합니다.

그런데 스왑이 시작되는 것 같았는데 부족하네요... 그래서 좀 더 스왑해 보도록 vm.swappiness권유 하려고 덧붙였습니다.100

그런 다음 프로세스를 다시 실행합니다. 전체 시스템은 매우 지연됩니다. 이는 프로세스가 성공적으로 완료될 때까지 많은 스와핑을 수행할 때 시스템이 수행하는 작업입니다.

두 번째 질문: 사용 가능한 메모리가 중요한 임계값 아래로 떨어지고 사용 가능한 스왑 공간이 확실히 충분한데도 커널이 사용 가능한 스왑 공간을 사용하지 않는 이유는 무엇입니까? 변화는 왜 vm.swappiness변화를 가져오는가?

고쳐 쓰다:

추가 테스트에서는 이 설정이 vm.swappiness신뢰할 수 있는 솔루션이 아닌 것으로 나타났습니다. 으로 설정한 경우에도 vm.swappiness몇 가지 실패가 발생했습니다 100. 그것가능한프로세스가 성공적으로 완료될 확률이 높아지지만 확실하지 않습니다.

답변1

사용 가능한 스왑 공간이 완전히 사용되기 전에 OOM 이벤트가 발생할 수 있는 데에는 여러 가지 이유가 있으며, OOM 이벤트가 OOM 킬러 스레드를 트리거하거나 더 나쁜 신호를 유발할 수 있습니다.

A/ 일반적인 메모리 할당 및 OOM 이벤트 정보
커널 개발자들은 많은 프로그램을 알고 있기 때문에malloc()기억에 남는다"혹시라도” 그리고 너무 많이 사용하지 마십시오. 적어도 시스템에서 실행 중인 모든 프로세스가 동시에 요청한 메모리가 필요하지 않을 것이라고 정적으로 기대하고 커널은 실제로 malloc(또는 친구)에서 메모리를 예약하지 않습니다. )
대신 실제 매핑이 발생하기 위해 메모리에 대한 A 쓰기 액세스(필연적으로 페이지 오류가 발생함)를 기다립니다 .
이때 메모리를 즉시 사용할 수 없으면 커널은 더 나은 날을 기다립니다( 1) 더 좋은 날이 빨리 오지 않으면 OOM 이벤트에 따라 OOM 이벤트가 트리거됩니다.일부 sysctl 설정(panic_on_oom), OOM-killer를 실행하거나 커널 패닉을 발생시킵니다.

B/ 스왑 영역의 여유 공간이 아무리 많아도 OOM 이벤트가 발생하는 이유는 무엇입니까?(2)

  • B.1/ 스왑 프로세스가 공간을 확보할 만큼 빠르지 않기 때문에:
    §A에 표시된 것처럼 커널은 일부 메모리를 사용할 수 있을 때까지 오래 기다리지 않습니다. 따라서 실행 중인 프로세스가 없으면 일부 메모리가 확보됩니다.그리고파일 시스템 캐시는 최소한으로 줄어들었으므로 교체하는 것이 메모리 페이지를 확보할 수 있는 유일한 방법입니다. 이는 유예 기간에 맞지 않습니다. Gig 메모리를 교체할 수 있더라도 OOM 이벤트가 발생합니다.
    디스크에 대한 임의 액세스는 느리고, 스왑 공간은 실행 중인 프로세스에서 사용하는 파일 시스템과 동일한 디스크에 있을 수 있으므로 스왑 영역에 대한 액세스는 훨씬 더 느립니다.
    그래도 시스템이 이러한 상황에 빠지지 않도록 하는 방법이 있습니다. 기억하다아킬레스와 거북이: 가능한 한 빨리 교체를 시작하십시오. 시스템에 더 이상 물리적 메모리가 필요하지 않으면 페이지 이동을 시작합니다.
    이것이 바로 당신이 실제로간접(3)증가하면 얻으려고 노력하십시오.교환성. 그러나 이는 설정의 부작용일 뿐이므로"최고"설정은 표준 편차가 높고 작업 부하에 크게 의존합니다. 벤치마크가 필요합니다. (4)(5)
  • B.2: 시스템은 교환할 수 있는 모든 것을 교환했기 때문에
    프로세스 사용량mlock()설계상 교체 불가능이 보장된 모든 페이지를 얻기 위해 시스템 호출이 수행됩니다. 더 나쁜? mlockall()(6)
    이로 인해 상당수의 MB가 스왑 불가능하게 됩니다.
    거대한 TLB 페이지또한 메모리 부족으로 인해 교체할 수 없는 경우 cat /proc/meminfo해당 목적을 위해 예약된 메모리 양이 보고됩니다.

C/ 메모리 부족이 높을 때 스레드가 종료될 수 있지만 OOM-killer는 아무것도 기록하지 않는 이유. (7)

  • C.1: 애플리케이션별 설계
    초과 할당 결정은 malloc릴리스 시 커널에 의해 이루어집니다. 하지만커널의 기본값은"낙관적 전략", 커널은 예약 요청을 거부하고 malloc()호출 스레드에 NULL 포인터를 반환합니다. 이는 항상 발생할 수 있습니다.
    이 경우 호출 프로세스가 이 예외를 처리하는 방법에 따라 요청을 업데이트할 더 나은 시간을 기다리거나 정상적으로 중단하거나 심지어 무시하고 segfault를 수행하여 종료되거나 상위 계층의 연속 현상이 발생합니다. 조기에 종료되어 OOM-killer 개입 없이도 상당한 양의 메모리가 확보됩니다. (그리고 다시 스왑에 남은 공간에 관계없이)
  • C.2/ 일부 스레드가 불쾌한 신호를 포착했기 때문에 시스템은 대형 페이지의 과잉 할당도 허용할 수 있으므로, 페이지가 누락되었을 때 대형 페이지가 없는 경우,임무는 SIGBUS로 전송되고 종종 불행하게도 죽습니다..

1:어 허더 나은 밀리초실제로는 최대 6번까지 확인하기 때문에 그 사이에 몇 나노초 정도 대기합니다. 이 숫자는 현재 오래된 커널에 대한 내 기억에 속하며 그 이후로 변경되었을 수 있습니다.

2:엄밀히 말하면 Linux는 그렇지 않습니다.교환~부터교환전체 프로세스 주소 공간을 디스크로 전송하는 것을 의미합니다. 리눅스는 실제로 구현페이징실제로 단일 페이지를 전송하기 때문입니다. 그러나 문서와 토론에서는교환… 그러면 그렇게 해.

삼: "간접적으로"스와핑을 일찍 시작하는 것은 이 설정의 부작용일 뿐이므로 주로 파일 시스템 캐시와 프로세스 페이지에 대한 선호도를 알려주기 위한 것입니다.
파일 시스템의 높은 IO 오버헤드로 인해 Linux는 캐싱에 최대한 많은 물리적 메모리를 사용합니다.
swappiness 값이 높을수록 시스템은 프로세스가 시작될 때 프로세스 페이지를 더 적극적으로 교환하며, 이로 인해 메모리 부족으로 인해 신속하게 회수할 수 있는 캐시 페이지 수가 늘어납니다.

4:그건 그렇고, 이것은 또한 귀하의 질문의 반대 측면을 설명합니다. 사용 가능한 여유 RAM이 많을 때 왜 시스템을 교체합니까?

5:주요 조직(RHEL, ORACLE...)이 교환성을 엄격한 최소값으로 설정하도록 권장하는 것을 볼 수 있지만... (그리고 더 많은 RAM을 구입...) Morton(선도적인 커널 개발자)은 값을 100으로 설정할 것을 강력히 권장합니다. .
기술의 가용성으로, 예를 들어교환, 파일 시스템 IO보다 스와핑을 더 저렴하게 만들 수 있으므로 100보다 큰 스와핑 값은 말도 안되는 일이 아닙니다.

6:

  mlockall() locks all pages mapped into the address space of the
   calling process.  This includes the pages of the code, data, and
   stack segment, as well as shared libraries, user space kernel
   data, shared memory, and memory-mapped files.  All mapped pages
   are guaranteed to be resident in RAM when the call returns
   successfully; the pages are guaranteed to stay in RAM until later
   unlocked.

7:활성화된 경우에도 OOM 킬러는 다소 게으르고 성가신 작업이 스스로 종료되도록 하는 것을 선호한다는 점을 명심하십시오. 그래서 범인의 신호가 기다리고 있다면... OOM 킬러는 그들이 조치를 취하기를 기다리고 있을 것입니다... 혹시라도...

답변2

우선 감사드리고 싶습니다.MC68020시간을 내어 이 문제를 조사해 주셔서 감사합니다. 공교롭게도 그들의 대답은 이 경우에 실제로 무슨 일이 일어나고 있는지를 다루지 않습니다. 하지만 그들은 좋은 대답이고 미래에 대한 유용한 참고 자료이기 때문에 어쨌든 현상금을 받았습니다.

저도 감사드리고 싶습니다필립 쿨린그의 대답은 완전히 정확하지는 않았지만 나에게 올바른 방향을 제시해주었습니다.

문제는 다음과 같습니다.시스템 관리 도구.

문제와 해결 방법은 다음과 같습니다.Ubuntu 22.04에서 시스템 OOM 프로세스 킬러를 비활성화하는 방법은 무엇입니까?

간단히 말해서:

systemctl disable --now systemd-oomd
systemctl mask systemd-oomd

이제 시스템 서비스가 경고 없이 전체 프로세스 트리를 종료하지 않고도 매번 프로세스를 완료할 때까지 안정적으로 실행할 수 있습니다.

답변3

OOM 킬러가 프로세스를 종료하게 만드는 원인이 무엇인지는 모르지만 그 사실은 문서화되어 있지 않습니다. 극단적인 경우 OOM Killer는 커널 로그를 디스크에 쓰는 프로세스를 중지할 수 있습니다. 귀하의 설명에 따르면 그럴 것 같지 않습니다.

귀하의 설명에서 두 가지 중요한 관련 세부정보를 추출하겠습니다.

  • OOM-Killer 로그 누락
  • 실제로 전체 프로세스 트리는 다음과 같이 구성됩니다.GUI 창사라졌습니다.

이것은 약간의 추측이지만 GUI 자체가 그것을 죽이는 것처럼 들립니다.

아마도 충돌한 것처럼 보이게 만든 범프였을 것입니다. 예를 들어 잦은 불안감으로 인해 브라우저가 충돌하는 사례를 본 적이 있습니다. 충돌 감지기는 활동을 확인하지 못하고 프로그램 자체에 문제가 있다고 가정하며 프로그램이 단지 커널의 응답을 기다리고 있다는 사실을 이해하지 못합니다.

나는 노력할 것이다콘솔 전환GUI 없이 명령줄에서 실행하세요. 이는 적어도 GNOME 자체의 간섭을 제거합니다.

관련 정보