내 Linux 시스템이 페이징에 가까워졌을 때(예: 내 경우에는 16GB 메모리가 거의 가득 찼고 16GB 스왑은 완전히 비어 있음) 새 프로세스 X가 일부 메모리를 할당하려고 하면 시스템이 완전히 잠깁니다. 즉, 불균형한 수의 페이지(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
(전체 코드를 반복하지는 않겠습니다). 이 방법은 시스템이 페이징의 가장자리에 있을 때 사용되므로 "부드러운" 방식으로 페이지를 교환합니다. 즉, 새 메모리 블록 할당을 천천히 요청하여(물론 시스템은 페이지와 페이지를 교환할 수 있어야 함) 새로운 요청을 따라잡으세요).
따라서 이 두 코드 조각을 컴파일한 후 각각의 exe fasteater 및 Sloweater를 각각 호출합니다. 다음을 수행해 보겠습니다.
1) 즐겨찾는 GUI를 실행합니다(물론 꼭 필요한 것은 아닙니다).
2) 일부 메모리/스왑 테이블 시작(예 watch -n 1 free
: )
3) fasteater x y
x가 기가바이트 단위이고 y가 메가바이트 단위인 여러 인스턴스를 시작합니다. RAM이 거의 채워질 때까지 이 작업을 수행합니다.
4) 인스턴스가 다시 시작되었습니다 sloweater x y
. 여기서 x는 GB 단위이고 y는 MB 단위입니다.
4단계 이후에 발생해야 하는 작업(내 시스템에서는 항상 발생함)은 메모리가 부족해지면 시스템이 완전히 잠긴다는 것입니다. GUI가 잠겨 있고, sshd가 잠겨 있습니다. 그러나 영원히는 아닙니다! Sloweater가 할당 요청을 완료한 후 시스템은 다음 동작과 함께 정상으로 돌아갑니다(초가 아닌 분 동안 잠긴 후...).
a) 메모리가 거의 가득 찼습니다.
b) 스왑 영역도 거의 꽉 찼습니다(처음에는 비어 있었음을 기억하세요).
c) oom Killer 개입이 없습니다.
스왑 파티션은 SSD에 있습니다. 따라서 시스템은 느린 속도의 느린(몇 메가바이트에 불과한) 요청을 위한 공간을 확보하기 위해 페이지를 램에서 스왑으로 점진적으로 이동할 수 없는 것으로 보입니다(아마도 방금 잠자기 상태가 된 빠른 속도에서).
이제 내가 틀렸다면 누군가 나를 정정할 수 있지만, 이는 현대 시스템이 이 상황에서 행동해야 하는 방식이 아닌 것 같습니다. 페이징이 지원되지 않고 가상 메모리 시스템이 몇 페이지 대신 프로세스의 전체 메모리 공간을 교환하면 기존 시스템 (WAAAAAY)처럼 행동하는 것 같습니다.
누군가 이것을 테스트할 수 있습니까? 어쩌면 누군가 BSD 시스템을 가지고 있을 수도 있습니다.
업데이트 1
나는 그 조언을 따랐다.마크 플롯닉아래 댓글에서는 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는 점진적으로 페이지를 교환하는 반면 속도 저하로 인해 10MB 메모리 블록이 모두 할당됩니다. 질문도 없고...여기서 무슨 일이 일어나고 있는 걸까요? !
업데이트 3:나는 제출했다허점커널 버그 추적기로. 관심을 좀 받는 것 같아서... 손가락이 교차합니다...
답변1
이것이 바로충격 보호에 존재합니다.
스왑 상태를 지속적으로 모니터링하고 무언가가 예기치 않게 많은 RAM을 차지하기 시작하면 RAM을 많이 사용하는 프로세스를 일시적으로 정지시켜 커널이 전체 시스템이 응답하지 않게 만들지 않고 일부 메모리를 스왑할 시간을 갖습니다.
답변2
단지 메모리만 할당할 뿐 실제로는 아무것도 넣지 않습니다. "일반" 프로그램은 블록을 할당한 다음 이를 사용하기 시작합니다. 할당은 메모리 사용량과 다릅니다.