이것이 리눅스 페이징의 동작 방식입니까?


26

새로운 프로세스 X가 일부 메모리를 할당하려고 시도하면 Linux 시스템이 페이징에 가까워 질 때 (즉, 16GB 램이 거의 찼고 16GB 스왑이 완전히 비어 있음) 시스템이 완전히 잠 깁니다. 즉, 불균형 한 양의 페이지 (X의 메모리 할당 요청의 총 크기 및 비율)가 스왑 아웃 될 때까지. GUI는 완전히 응답하지 않을뿐만 아니라 sshd와 같은 기본 서비스조차 완전히 차단됩니다.

이것들은 좀 더 "과학적인"방식으로이 행동을 유발하기 위해 사용하는 두 개의 코드 조각입니다. 첫 번째 숫자는 명령 행에서 두 개의 숫자 x, y를 얻고 x보다 많은 총 바이트가 할당 될 때까지 y 바이트의 여러 청크를 할당하고 초기화합니다. 그리고는 무한정 잠이 듭니다. 이것은 페이징 직전에 시스템을 가져 오는 데 사용됩니다.

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>

int main(int argc, char** argv) {
   long int max = -1;
   int mb = 0;
   long int size = 0;
   long int total = 0;
   char* buffer;

   if(argc > 1)
     {
       max = atol(argv[1]);
       size = atol(argv[2]);
     }
   printf("Max: %lu bytes\n", max);
   while((buffer=malloc(size)) != NULL && total < max) {
       memset(buffer, 0, size);
       mb++;
       total=mb*size;
       printf("Allocated %lu bytes\n", total);       
   }      
   sleep(3000000);
   return 0;
}

두 번째 코드는 첫 번째 코드와 정확히 일치한다는 점을 제외하고 첫 번째 코드와 정확히 일치 sleep(1);합니다 printf(전체 코드를 반복하지는 않음). 이것은 시스템이 페이징 직전에 "부드러운"방식으로 페이지를 스왑하도록하기 위해 사용됩니다. 즉, 새로운 메모리 청크 할당을 천천히 요청하여 시스템이 페이지를 스왑 아웃 할 수 있어야합니다. 새 요청을 따라야합니다).

두 코드 조각을 컴파일하여 각각의 exes fasteater와 sloweater를 호출 해 봅시다.

1) 좋아하는 GUI를 시작하십시오 (물론 꼭 필요한 것은 아닙니다)

2) (예를 몇 가지 MEM / 스왑 m 시작 watch -n 1 free)

3) fasteater x yx가 기가 바이트이고 y가 메가 바이트 인 여러 인스턴스를 시작 하십시오. 램이 거의 채워질 때까지하십시오.

4)의 인스턴스 하나를 sloweater x y다시 시작 하십시오. 여기서 x는 기가 바이트이고 y는 메가 바이트입니다.

단계 4) 후에 일어날 일은 (그리고 항상 내 시스템에서 발생합니다) 램을 다 사용한 직후에 시스템이 완전히 잠기 게됩니다. GUI가 잠겨 있습니다. sshd가 잠겨 있습니다. 그러나 영원히는 아닙니다! sloweater가 할당 요청을 완료하면이 상황에서 시스템은 몇 초가 아니라 몇 분 동안 잠금 상태로 돌아옵니다.

a) 램이 가득 찼습니다

b) 스왑도 가득 찼습니다 (처음에는 비어 있음을 기억하십시오)

c) oom killer 킬러 개입 없음.

스왑 파티션은 SSD에 있습니다. 따라서 시스템은 느린 eateat의 느린 (그리고 단지 몇 메가 바이트) 요청을위한 공간을 만들기 위해 페이지를 램에서 스왑으로 (아마 잠자고있는 fasteaters에서) 점진적으로 이동할 수없는 것 같습니다.

이제 내가 틀렸다면 누군가 나를 고치지 만,이 설정에서 현대 시스템이 작동 해야하는 방식은 아닙니다. 페이징에 대한 지원이 없었고 가상 메모리 시스템이 몇 페이지 대신 일부 프로세스의 전체 메모리 공간을 스왑 아웃했을 때 이전 시스템처럼 작동하는 것 같습니다.

누군가도 이것을 테스트 할 수 있습니까? 그리고 아마도 BSD 시스템을 가진 사람 일 수도 있습니다.

업데이트 1 아래 주석 에서 Mark Plotnick 의 조언을 따르고 vmstat 1 >out페이징 테스트를 진행 하기 전에 시작했습니다 . 아래 결과를 볼 수 있습니다 (스왑 개입없이 램이 채워지는 초기 부분 전체를 잘라 냈습니다).

procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
0  0   6144 160792      8 272868    0    0     0     0  281 1839  1  0 99  0  0
0  0   6144 177844      8 246096    0    0     0     0  425 2300  1  1 99  0  0
0  0   6144 168528      8 246112    0    0    16     0  293 1939  1  0 99  0  0
0  0   6144 158320      8 246116    0    0     0     0  261 1245  0  0 100  0  0
2  0  10752 161624      8 229024    0 4820 17148  4820  845 3656  1  2 97  0  0
2  0  10752 157300      8 228096    0    0 88348     0 2114 8902  0  5 94  1  0
0  0  10752 176108      8 200052    0    0 108312     0 2466 9772  1  5 91  3  0
0  0  10752 170040      8 196780    0    0 17380     0  507 1895  0  1 99  0  0
0 10  10752 160436      8 191244    0    0 346872    20 4184 17274  1  9 64 26  0
0 29 12033856 152888      8 116696 5992 15916880 1074132 15925816 819374 2473643  0 94  0  6  0
3 21 12031552 295644      8 136536 1188    0 11348     0 1362 3913  0  1 10 89  0
0 11 12030528 394072      8 151000 2016    0 17304     0  907 2867  0  1 13 86  0
0 11 12030016 485252      8 158528  708    0  7472     0  566 1680  0  1 23 77  0
0 11 12029248 605820      8 159608  900    0  2024     0  371 1289  0  0 31 69  0
0 11 12028992 725344      8 160472 1076    0  1204     0  387 1381  0  1 33 66  0
0 12 12028480 842276      8 162056  724    0  3112     0  357 1142  0  1 38 61  0
0 13 12027968 937828      8 162652  776    0  1312     0  363 1191  0  1 31 68  0
0  9 12027456 1085672      8 163260  656    0  1520     0  439 1497  0  0 30 69  0
0 10 12027200 1207624      8 163684  728    0   992     0  411 1268  0  0 42 58  0
0  9 12026688 1331492      8 164740  600    0  1732     0  392 1203  0  0 36 64  0
0  9 12026432 1458312      8 166020  628    0  1644     0  366 1176  0  0 33 66  0

보시다시피, 스왑이 시작 되 자마자 한 번에 15916880KB의 대규모 스왑 아웃이 발생하여 시스템이 정지되는 동안 지속됩니다. 그리고이 모든 것은 분명히 매 초마다 10MB를 요구하는 프로세스 (슬로 이터)에 의해 발생합니다.

업데이트 2 : FreeBSD를 빠르게 설치하고 Linux에서 사용하는 것과 동일한 할당 체계를 반복했습니다 ... 매우 부드럽습니다. FreeBSD는 페이지를 점진적으로 바꾸었고 sloweater는 10MB의 모든 메모리를 할당했습니다. 어떤 종류의 장애도 없습니다 ... WTF가 계속되고 있습니까?!

업데이트 3 : 커널 버그 추적기에 버그 를 신고했습니다 . 약간의 주목을 받고있는 것 같습니다 ... 손가락이 ......


2
내가 언급했듯이 모든 것이 잠겨 있습니다. 다른 시스템에서 ssh'ing을 시도했지만 시간이 초과되었습니다.
John Terragon

2
stdout 출력으로 vmstat 1을 시작하면 정지 될 것이라고 생각합니다. 하지만 당신은 옳 vmstat 1>somefile습니다. 시스템에서 직접 시작한 다음 시스템이 다시 활성화 된 후에보고되는 내용을 볼 수 있습니다. 나는 그것을 시도 할 것이다.
John Terragon

2
vmstat를 사용했습니다. 위의 업데이트 결과.
John Terragon

3
swappiness기본값은 60입니다 (변경하면 더 나은 결과를 제공하지 않음). vmstat실행에 사용 된 커널 은 4.14.35이지만 4.15, 4.16을 시도했지만 4.0 시리즈 (!)로 돌아갔습니다. 항상 동일한 동작입니다. 그리고 내가 이상한 배포판을 사용하고있는 것이 아니라 데비안입니다. 나는 데비안에서 커널 이미지를 사용하지 않지만 (내 구성에는 특별한 구성이 없습니다) 그중 하나를 시도했습니다 ... 동일한 동작.
John Terragon

2
커널 버그에 대한 매우 흥미로운 토론! 그리고이 문제를 격리하여 LUKS로 암호화 된 파티션을 교환하는 것처럼 보입니다. 답변을 편집하거나 직접 답변을 게시하고 싶을 수도 있습니다 (지금까지 알려진 해결 방법으로 LKML 토론이보다 결정적인 결과를 얻음에 따라 계속 업데이트 할 수 있습니다). Linux 커널 커뮤니티가 실제로 작동하는 것을 보는 것은 정말 인상적입니다! 😁
filbranden

답변:


1

이것이 바로 스래쉬 방지 기능 입니다.

끊임없이 스와핑 상태를 모니터링하고 실수로 많은 RAM을 점유하기 시작하면 RAM 욕심 많은 프로세스를 일시적으로 중지하므로 커널은 전체 시스템을 응답하지 않고 일부 메모리를 스왑 할 시간이 있습니다.


-3

당신은 메모리를 할당하고 있습니다-실제로 아무것도 넣지 않습니다. "정상적인"프로그램은 청크를 할당 한 다음 사용을 시작합니다. 할당은 메모리 사용량과 다릅니다.


3
Unix StackExchange에 게시하는 것을 환영합니다. 데이터를 넣지 만 데이터는 0이됩니다. memset ()을 참조하십시오. Linux 커널은 가상 페이지에 쓰 자마자 실제 RAM 페이지를 제공합니다. 작성된 특정 값을 보지 않습니다.
sourcejedi

실제로 2GB 사용, 6GB 무료로 시작하여 데스크탑에서 이것을 컴파일하고 실행했습니다. 실제로 처음에는 느린 속도로 스왑 아웃되었고 한계에 도달했을 때만 적극적으로 스왑 아웃되었으므로 다양한 GUI 작업이 중단되었습니다.
Jeremy Boden
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.