이것은 오래된 게시물이지만 여전히 여기에 내 생각을 자유롭게 할 수 있습니다.
아래에서 시작하여 Linux는 먼저 메모리를 페이지 (일반적으로 x86_64 시스템의 페이지 당 4K)로 나눕니다. 그 후, MMU (Memory Management Unit)를 사용하여 물리적 메모리로 매핑되는 가상 메모리가 생성됩니다.
프로세스에는 가상 메모리 영역에서 메모리가 할당되므로 / proc / meminfo가 표시되면 VMalloc *가 가상 메모리 세부 정보로 표시됩니다.
메모리를 요청하는 프로세스 (예 : 300MB-웹 브라우저)가 있다고 가정 해 봅시다. 프로세스는 가상 메모리에서 300MB로 할당되지만 메모리 매핑 (실제 메모리에 매핑) 일 필요는 없습니다. 메모리 관리를위한 "Copy on Write"개념이 있는데, 프로세스가 실제로 가상 메모리에서 할당 된 메모리를 사용하는 경우 (즉, 메모리에서 일부 쓰기를 수행하는 경우) 물리적 메모리에만 매핑됩니다. 이를 통해 커널이 다중 프로세스 환경에서 효율적으로 올바르게 작동 할 수 있습니다.
캐시 란 무엇입니까?
프로세스가 사용하는 많은 메모리가 공유됩니다. glibc 라이브러리는 거의 모든 프로세스에서 사용됩니다. 모든 프로세스가 동일한 메모리 위치에 액세스하여 작업을 수행 할 수있을 때 glibc의 여러 복사본을 메모리에 보관하는 시점은 무엇입니까? 이와 같이 자주 사용되는 리소스는 캐시에 보관되므로 프로세스 요구시 동일한 메모리 위치를 참조 할 수 있습니다. 디스크에서 glibc 등을 다시 읽는 것은 시간이 많이 걸리므로 프로세스 속도를 높이는 데 도움이됩니다.
위의 말은 공유 라이브러리에 대한 것이며 파일 읽기와 비슷합니다. 큰 파일 (예 : 100-200MB)을 처음 읽으면 시간이 많이 걸립니다. 그러나 동일한 읽기를 다시 시도하면 더 빠릅니다. 데이터가 메모리에 캐시되었으며 모든 블록에 대해 다시 읽기가 수행되지 않았습니다.
버퍼 란?
버퍼와 관련하여 프로세스가 파일 I / O를 수행 할 때 디스크의 데이터를 쓰기 위해 커널 버퍼에 의존합니다. 프로세스는 커널에게 작업을 수행하도록 요청합니다. 따라서 프로세스를 대신하여 커널은 데이터를 "버퍼"에 기록하고 프로세스에 쓰기가 완료되었음을 알립니다. 비동기 방식으로 커널은 버퍼의이 데이터를 디스크와 계속 동기화합니다. 이런 식으로 프로세스는 커널에 의존하여 데이터를 디스크에 동기화 할 정확한 시간을 선택하고 프로세스는 계속 진행될 수 있습니다. 이것은 일반적인 프로세스가 수행하는 일반적인 I / O입니다. 그러나 실제로 디스크에서 I / O가 수행되는지 확인해야하는 특수 프로세스는 다른 메커니즘을 사용하여 디스크에서 I / O를 수행 할 수 있습니다. 오픈 소스 유틸리티 중 일부는 libaio입니다. 또한 프로세스 컨텍스트에서 열린 FD에 명시 적 동기화를 호출하는 방법이 있습니다.
그러면 페이지 결함은 무엇입니까?
바이너리가 약 300MB 인 프로세스 (예 : 웹 브라우저)를 시작할 때의 예를 고려하십시오. 그러나 전체 300MB의 웹 브라우저 바이너리가 즉시 작동하지 않습니다. 프로세스는 코드에서 함수 간 이동을 계속합니다. 앞에서 언급했듯이 가상 메모리는 300MB를 소비하지만 모든 메모리가 실제 메모리에 매핑되는 것은 아닙니다 (RSS-상주 메모리가 적을 수 있습니다. 상단 출력 참조). 코드 실행이 실제로 물리적으로 매핑되지 않은 지점에 도달하면 페이지 오류가 발생합니다. 커널은이 메모리를 물리적으로 매핑하고 메모리 페이지를 프로세스에 연결합니다. 이러한 페이지 오류를 "사소한 페이지 오류"라고합니다. 마찬가지로 프로세스가 파일 I / O를 수행 할 때 주요 페이지 결함이 발생합니다.
언제 그리고 왜 스왑 아웃이 발생합니까?
상황 1 :
위의 세부 사항과 함께, 많은 양의 메모리가 메모리 매핑되는 시나리오를 고려하십시오. 이제 메모리가 필요한 프로세스가 시작됩니다. 위에서 논의한 것처럼 커널은 메모리 매핑을 수행 할 것입니다. 그러나 메모리를 매핑하는 데 사용 가능한 물리적 RAM이 충분하지 않습니다. 이제 커널은 먼저 캐시를 살펴보고 사용하지 않는 오래된 메모리 페이지를 갖게됩니다. 해당 페이지를 별도의 파티션 (SWAP)으로 플러시하고 일부 페이지를 비우고 비워진 페이지를 새로 오는 요청에 매핑합니다. 디스크 쓰기가 솔리드 스테이트 RAM보다 훨씬 느리기 때문에이 프로세스에는 많은 시간이 걸리므로 속도가 느려집니다.
상황 2 :
시스템에서 사용 가능한 많은 여유 메모리를 볼 수 있다고 가정합니다. 그럼에도 불구하고 많은 스왑 아웃이 발생하고 있음을 알 수 있습니다. 메모리 조각화 문제가있을 수 있습니다. 커널에서 50MB의 연속 메모리가 필요한 프로세스를 고려하십시오. (인접을 명심하십시오). 분명히 커널은 다른 프로세스에 무작위로 페이지를 할당하고 그 중 일부를 해제했을 것입니다. 그러나 연속 메모리를 요구할 때는 프로세스 요구를 만족시키는 청크를 찾아야합니다. 그러한 메모리를 확보 할 수없는 경우 일부 오래된 메모리 페이지를 교체 한 다음 연속적인 페이지를 할당해야합니다. 그러한 경우에도 SWAP가 발생합니다. 커널 버전 2.6 이상부터는 이러한 조각화 문제가 상당히 줄었습니다. 그러나 시스템이 오랫동안 실행되는 경우에도 여전히 이러한 문제가 발생할 수 있습니다.
이 예를 참조하십시오 ( vmstat 출력 )
2016-10-29 03:55:32 procs -----------memory---------- ---swap-- -----io---- --system-- -----cpu------
2016-10-29 03:55:32 r b swpd free buff cache si so bi bo in cs us sy id wa st
2016-10-30 03:56:04 19 23 2914752 4692144 3344908 12162628 1660 1 8803 12701 4336 37487 14 7 40 38 0
2016-10-30 03:56:34 3 20 2889296 4977580 3345316 12026752 2109 2 8445 14665 4656 36294 12 7 46 34 0
2016-10-30 03:57:04 1 11 3418868 4939716 3347804 11536356 586 4744 2547 9535 3086 24450 6 3 59 33 0 <<<-----
2016-10-30 03:57:34 3 19 3456252 5449884 3348400 11489728 3291 13371 6407 17957 2997 22556 6 4 66 24 0
2016-10-30 03:58:04 7 6 4194500 5663580 3349552 10857424 2407 12240 3824 14560 2295 18237 4 2 65 29 0
2016-10-30 03:58:34 2 16 4203036 5986864 3348908 10838492 4601 16639 7219 18808 2575 21563 6 4 60 31 0
2016-10-30 03:59:04 3 14 4205652 6059196 3348760 10821448 6624 1597 9431 4357 1750 20471 6 2 60 31 0
2016-10-30 03:59:34 2 24 4206968 6053160 3348876 10777216 5221 2067 10106 7377 1731 19161 3 3 62 32 0
2016-10-30 04:00:04 0 13 4205172 6005084 3348932 10785896 6236 1609 10330 6264 1739 20348 4 2 67 26 0
2016-10-30 04:00:34 4 11 4206420 5996396 3348976 10770220 6554 1253 10382 4896 1964 42981 10 5 58 27 0
2016-10-30 04:01:04 6 4 4177176 5878852 3348988 10825840 8682 765 10126 2716 1731 32949 8 4 69 19 0
@ 2016-10-30 03:57:04, 우리는 여전히 충분한 양의 여유 RAM이 있음을 알 수 있습니다. 그러나 그때도 스왑 아웃이 발생했습니다. 우리는이 시점에서 프로세스 트리를 점검했지만, 많은 양의 메모리 (여유 메모리 이상)를 요구하는 프로세스는 나타나지 않았습니다. 명백한 의심은 위에서 설명한 상황 2였다. 위의 buddyinfo 및 zoneinfo 로그를 확인했습니다 (echo m> / proc / sysrq-trigger를 사용하여이를 확인하면 출력은 syslog로갑니다).
우리 시스템의 일반적인 시스템의 경우 영역 정보를 비교하면 다음과 같습니다. 캐시 / 프리 / 로우 메모리에 대한 그래프도 아래에 언급되어 있습니다.
정보를 보면 노드 0 및 노드 1 정상에 메모리 조각화가 있음이 분명합니다 (노드는 NUMA 기반 시스템이므로 여러 노드 (시스템의 정보를 확인하려면 numactl 참조)).
메모리 조각화는 사용 가능한 메모리가있는 경우에도 스왑 사용량이 증가 할 수있는 이유입니다.