나는 커널 개발자는 아니지만이 soooo를 여러 번 실행했기 때문에이 문제에 대해 철학적으로 수년을 보냈습니다. 나는 실제로 모든 상황에 대한 은유를 생각해 냈습니다. 나는 나의 이야기에서 "스왑"과 같은 것은 존재하지 않는다고 가정 할 것이다. 스왑은 요즘 어쨌든 32GB RAM에서는 의미가 없습니다.
파이프를 통해 각 건물에 물이 연결되어 있고 마을에서 수용 인원을 관리해야하는 이웃을 상상해보십시오. 초당 100 단위의 물만 생산한다고 가정합니다 (저장 탱크가 없기 때문에 사용되지 않은 모든 용량이 낭비됩니다). 각 집 (집 = 작은 앱, 터미널, 시계 위젯 등)에는 초당 1 단위의 물이 필요합니다. 인구가 90 명이므로 모두가 충분한 물을 섭취하기 때문에 이것은 모두 훌륭하고 좋습니다.
이제 시장 (= 귀하)은 큰 식당 (= 브라우저)을 열겠다고 결정합니다. 이 식당에는 여러 요리사가 있습니다 (= 브라우저 탭). 각 요리사는 초당 1 단위의 물이 필요합니다. 당신은 10 요리사로 시작하므로, 전체 지역의 총 물 소비량은 100 단위의 물로 여전히 좋습니다.
이제 재미있는 것들이 시작됩니다 : 당신은 분명히 당신이 가지고 있지 않은 총 물 요구량을 101로 만드는 다른 요리사를 식당에 고용합니다. 무언가를해야합니다.
물 관리 (= 커널)에는 3 가지 옵션이 있습니다.
1. 첫 번째 옵션은 최근에 물을 사용하지 않은 주택에 대한 서비스 연결을 끊는 것입니다. 괜찮지 만 연결이 끊긴 집에서 물을 다시 사용하려면 긴 등록 과정을 다시 거쳐야합니다. 관리는 여러 가정을 분리하여 더 많은 수자원을 확보 할 수 있습니다. 실제로, 그들은 최근에 물을 사용하지 않은 모든 주택을 분리하여 항상 무료로 사용할 수있는 양을 유지합니다.
당신의 도시는 계속 기능을 발휘하지만 단점은 진전이 멈춘다는 것입니다. 대부분의 시간은 용수 관리를 통해 서비스를 복원하는 데 소비됩니다.
이것이 커널이 파일 지원 페이지에서 수행하는 작업입니다. 크롬과 같은 큰 실행 파일을 실행하면 파일이 메모리에 복사됩니다. 메모리가 부족하거나 최근에 액세스하지 않은 부품이있는 경우 커널은 해당 부품을 디스크에서 다시로드 할 수 있기 때문에 해당 부품을 제거 할 수 있습니다. 이 작업을 너무 많이 수행하면 모든 것이 디스크 IO를 기다리고 있기 때문에 데스크탑이 정지됩니다. 커널은 많은 IO를 시작할 때 가장 최근에 사용 된 페이지를 많이 삭제합니다. DVD 이미지와 같은 큰 파일을 여러 개 복사 한 후 백그라운드 앱으로 전환하는 데 시간이 오래 걸리는 이유입니다.
내가 hickups를 싫어하고 당신은 그것을 제어 할 수 없기 때문에 이것은 나를 위해 가장 성가신 행동입니다. 스위치를 끄는 것이 좋을 것입니다. 나는 라인을 따라 뭔가를 생각하고 있습니다
sed -i 's/may_unmap = 1/may_unmap = (vm_swappiness >= 0)/' mm/vmscan.c
그런 다음 vm_swappiness를 -1로 설정하여이를 비활성화 할 수 있습니다. 이것은 내 작은 테스트에서 꽤 잘 작동했지만 아아 나는 커널 개발자가 아니므로 누구에게도 보내지 않았습니다 (그리고 분명히 위의 작은 수정은 완료되지 않았습니다).
2.경영진은 새로운 요리사의 물 요청을 거부 할 수 있습니다. 처음에는 좋은 생각처럼 들립니다. 그러나 두 가지 단점이 있습니다. 첫째, 물을 사용하지 않더라도 많은 물을 신청하는 회사가 있습니다. 이를 수행 할 수있는 한 가지 이유는 추가 물이 필요할 때마다 물 관리와 대화하는 모든 오버 헤드를 피하기 위해서입니다. 하루 중 시간에 따라 물 사용량이 증가하거나 감소합니다. 예를 들어 식당의 경우 정오에 자정에 비해 훨씬 더 많은 물이 필요합니다. 그래서 그들은 가능한 모든 물을 요구하지만 자정 동안 물 할당을 낭비합니다. 문제는 모든 회사가 최대 사용량을 정확하게 예측할 수 없기 때문에 더 많은 요청에 대해 걱정할 필요가 없기 때문에 훨씬 더 많이 요청한다는 것입니다.
이것은 자바의 가상 머신이하는 일이다 : 시작시에 많은 메모리를 할당하고 그로부터 작동한다. 기본적으로 커널은 Java 앱이 실제로 사용하기 시작할 때만 메모리를 할당합니다. 그러나 오버 커밋을 비활성화하면 커널이 예약을 심각하게 받아들입니다. 실제로 자원이있는 경우에만 할당이 성공할 수 있습니다.
그러나이 방법에는 다른 심각한 문제가 있습니다. 한 회사가 10 단계가 아닌 매일 물 한 단위를 요청하기 시작한다고 가정 해 봅시다. 결국 0 개의 프리 유닛이있는 상태가됩니다. 이제이 회사는 더 많은 것을 할당 할 수 없습니다. 어쨌든 대기업에 관심이있는 사람은 괜찮습니다. 그러나 문제는 작은 집에서도 더 많은 물을 요청할 수 없다는 것입니다! 관광객의 갑작스런 유입을 처리하기 위해 작은 공중 화장실을 만들 수는 없습니다. 근처 숲에서 화재를위한 비상 용수를 제공 할 수 없습니다.
컴퓨터 용어로 : 초과 커밋없이 메모리가 부족한 상황에서는 새로운 xterm을 열 수 없으며 컴퓨터로 ssh 할 수 없으며 새로운 탭을 열어 검색 할 수 없습니다 수정. 다시 말해 오버 커밋을 비활성화하면 메모리가 부족할 때 데스크톱을 사용할 수 없게됩니다.
3. 이제 회사가 너무 많은 물을 사용하기 시작할 때 문제를 처리하는 흥미로운 방법이 있습니다. 수자원 관리가 폭발합니다! 말 그대로 : 식당 사이트로 이동하여 다이너마이트를 던져 폭발 할 때까지 기다립니다. 이것은 새로운 사람들이 들어올 수 있고 공공 화장실 등을 만들 수 있도록 도시의 물 요구량을 즉시 줄입니다. 시장으로서 당신은 이번에는 물이 덜 필요하다는 희망에 따라 식당을 재건 할 수 있습니다. 예를 들어, 사람들이 이미 너무 많으면 사람들이 식당에 가지 말라고 지시합니다 (예 : 브라우저 탭이 적게 열립니다).
이것은 실제로 모든 옵션이 부족할 때 커널이하는 일이며 메모리가 필요합니다. OOM 킬러라고합니다. 많은 휴리스틱을 기반으로 한 큰 응용 프로그램을 선택하고 종료하여 많은 메모리를 확보하지만 반응 형 데스크톱을 유지 관리합니다. 실제로 안드로이드 커널은 훨씬 더 적극적 으로이 작업을 수행합니다. 메모리가 부족할 때 가장 최근에 사용한 앱을 종료합니다 (마지막 수단으로 만 사용하는 주식 커널과 비교). 이것을 안드로이드에서는 바이킹 킬러라고합니다.
나는 이것이 문제에 대한 가장 간단한 해결책 중 하나라고 생각합니다. 이보다 더 많은 옵션을 가지고 있지 않기 때문에 나중에 빨리 극복하지 않겠습니까? 문제는 커널이 때때로 OOM 킬러 호출을 피하기 위해 많은 작업을 수행한다는 것입니다. 그렇기 때문에 데스크탑이 매우 느리고 커널이 아무 것도하지 않는 것을 볼 수 있습니다. 그러나 다행히도 OOM 킬러를 직접 호출 할 수있는 옵션이 있습니다! 먼저 매직 sysrq 키가 활성화되어 있는지 확인한 echo 1 | sudo tee
/proc/sys/kernel/sysrq
다음 (예 :) 커널 메모리가 부족할 때마다 Alt + SysRQ, Alt + f를 누르십시오.
좋아, 모두 훌륭하지만 시도해보고 싶습니까? 메모리 부족 상황은 재현하기가 매우 쉽습니다. 나는 그것을 위해 매우 간단한 응용 프로그램이 있습니다. 두 번 실행해야합니다. 첫 번째 실행은 사용 가능한 RAM의 양을 결정하고 두 번째 실행은 메모리 부족 상황을 만듭니다. 이 방법은 스왑이 비활성화 된 것으로 가정합니다 (예 :) sudo swapoff -a
. 코드 및 사용법은 다음과 같습니다.
// gcc -std=c99 -Wall -Wextra -Werror -g -o eatmem eatmem.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
int main(int argc, char** argv)
{
int limit = 123456789;
if (argc >= 2) {
limit = atoi(argv[1]);
}
setbuf(stdout, NULL);
for (int i = 1; i <= limit; i++) {
memset(malloc(1 << 20), 1, 1 << 20);
printf("\rAllocated %5d MiB.", i);
}
sleep(10000);
return 0;
}
사용 방법은 다음과 같습니다.
$ gcc -std=c99 -Wall -Wextra -Werror -g -o eatmem eatmem.c
$ ./eatmem
Allocated 31118 MiB.Killed
$ ./eatmem 31110
Allocated 31110 MiB.Killed
첫 번째 호출에서 31,118 MiB의 사용 가능한 RAM이 있음을 발견했습니다. 따라서 응용 프로그램에 31,110 MiB RAM을 할당하여 커널이 죽이지 않고 거의 모든 메모리를 소비하도록했습니다. 내 시스템이 멈췄습니다. 마우스 포인터조차도 움직이지 않았습니다. Alt + SysRQ, Alt + f를 눌렀을 때 eatmem 프로세스가 종료되고 시스템이 복원되었습니다.
메모리가 부족한 상황에서 수행하는 옵션을 다루었지만 가장 위험한 방법은 다른 위험한 상황과 마찬가지로 처음에는 피하는 것입니다. 이를 수행하는 방법에는 여러 가지가 있습니다. 내가 본 한 가지 일반적인 방법은 브라우저와 같은 오작동하는 응용 프로그램을 나머지 시스템과 다른 컨테이너에 넣는 것입니다. 이 경우 브라우저는 데스크탑에 영향을 줄 수 없습니다. 그러나 예방 자체는 질문의 범위를 벗어나므로 그것에 대해 쓰지 않을 것입니다.
TL; DR : 현재 페이징을 완전히 피할 수있는 방법은 없지만 오버 커밋을 비활성화하여 전체 시스템 정지를 완화 할 수 있습니다. 그러나 메모리 부족 상황에서는 시스템을 계속 사용할 수 없지만 다른 방식으로 사용할 수는 없습니다. 위와 상관없이 메모리가 부족한 상황에서는 Alt + SysRQ, Alt + f를 눌러 커널이 선택한 많은 프로세스를 종료하십시오. 몇 초 후에 시스템이 응답 성을 복원해야합니다. 이것은 매직 sysrq 키가 활성화되어 있다고 가정합니다 (기본적으로는 아님).