Linux에서 메모리 오버커밋의 목적은 무엇입니까?

Linux에서 메모리 오버커밋의 목적은 무엇입니까?

나는 대해 알고있다메모리 과잉 할당나는 그것을 매우 싫어하고 일반적으로 비활성화합니다. 그래요아니요생각설정값시스템 프로세스(예: 실행 중인 프로세스) 기반sudo또는접미사) 그러나 일반적인 Linux 프로세스는 관리자 권한 없이 일부 사용자에 의해 일부 명령줄에서 시작됩니다.

잘 작성된 프로그램은 사용 가능한 것 malloc보다 더 많은 메모리를 사용하고 사용 중에 충돌이 발생할 수 mmap있습니다 . malloc메모리 오버커밋이 없으면 mallocOR은 mmap실패하며 잘 작성된 프로그램은 해당 실패를 포착합니다. malloc잘못 작성된 프로그램(실패 확인 없이 사용)은 실패 결과를 사용할 때 충돌이 발생합니다 malloc.

틀림없이가상 주소 공간mmap(으로 확장됨 malloc)은 RAM과 다릅니다(RAM은 커널에 의해 관리되는 리소스입니다. 참조).이것;프로세스의 가상 주소 공간이 다음으로 초기화됩니다.실행(2)mmap& 에 의해 확장되므로 sbrk소비하지 않습니다.곧장메모리만가상 메모리).

RAM 사용 최적화는 다음을 통해 달성할 수 있습니다.미친 웨스(2)MADV_DONTNEED(이는 실제로 필요할 때 커널을 사용하여 일부 페이지를 디스크로 교환하라는 힌트를 줄 수 있습니다 .) 과도하게 커밋하려는 프로그램은 다음을 사용할 수 있습니다.매핑(2)그리고 MAP_NORESERVE. 메모리 오버커밋에 대한 나의 이해는 모든 메모리 맵( execve또는 을 통해 mmap)이 암시적 으로MAP_NORESERVE

내 의견은 버그가 많은 프로그램에 유용하다는 것입니다. 하지만 IMHO는 실제 개발자가 해야 할 일입니다.언제나관련 가상 주소 공간 변경 기능의 점검 및 실패 malloc( mmap예:여기). 내가 조사한 대부분의 무료 소프트웨어 프로그램에는 소스 코드에 이러한 검사가 포함되어 있습니다.xmalloc기능....

실제로 합리적이고 유용한 방식으로 메모리 재사용을 요구하고 사용하는 실제 프로그램(예: 일반적인 Linux 배포판에 패키지됨)이 있습니까? 나는 그들을 모른다!

메모리 재사용을 비활성화하면 어떤 단점이 있나요? 많은 오래된 Unix(예: 지난 세기의 SunOS4, SunOS5)에는 이 기능이 없으며 IMHO malloc(그리고 아마도 일반적인 시스템 전체 성능 malloc)도 그다지 나쁘지 않습니다(그 이후의 개선은 메모리 과잉 할당과 관련이 없습니다).

나는 메모리 과잉 할당이 게으른 프로그래머의 실수라고 생각합니다.

프로그램 사용자는 일부 리소스 제한을 설정할 수 있습니다.제한 설정(2)RLIMIT_AS상위 프로세스에 의해 호출됩니다(예: ulimit내장 /bin/bash; 또는 limit내장다루기 힘든at, 또는 , crontab, , ... 와 같은 최신 동등물 또는 상위 프로세스(최종 pid 1 또는 해당 최신 프로세스 batch까지)/sbin/init체계변형).

답변1

과잉 커밋의 이유는 물리적 RAM의 활용도가 떨어지는 것을 방지하기 위한 것입니다. 프로세스에 의해 할당된 가상 메모리의 양과 실제 물리적 페이지 프레임에 매핑된 가상 메모리의 양에는 차이가 있습니다. 실제로 프로세스가 시작된 후에는 RAM이 거의 예약되지 않습니다. 이는 요구 페이징 때문입니다. 프로세스에는 가상 메모리 레이아웃이 있지만 가상 메모리 주소에서 물리적 페이지 프레임으로의 매핑은 메모리를 읽거나 쓸 때까지 설정되지 않습니다.

프로그램은 일반적으로 전체 가상 메모리 공간을 사용하지 않으며, 영향을 받는 메모리 영역은 프로그램 런타임 중에 변경됩니다. 예를 들어 실행 시작 시에만 실행되는 초기화 코드가 포함된 페이지 프레임에 대한 매핑을 삭제할 수 있으며 해당 페이지 프레임을 다른 매핑에 사용할 수 있습니다.

데이터에도 동일하게 적용됩니다. 프로그램이 호출되면 malloc데이터를 저장할 만큼 큰 연속 가상 주소 공간을 예약합니다. 그러나 물리적 페이지 프레임에 대한 매핑은 해당 페이지가 실제로 사용될 때까지 설정되지 않으며,혹시라도. 또는 프로그램 스택에 대해 생각해 보십시오. 각 프로세스는 스택 전용 가상 메모리의 상당히 큰 연속 영역(보통 8MB)을 얻습니다. 프로세스는 일반적으로 이 스택 공간의 작은 부분만 사용합니다. 작고 잘 실행되는 프로그램은 훨씬 더 적게 사용합니다.

Linux 컴퓨터에는 일반적으로 수명 주기의 여러 단계에서 실행되는 다양한 이기종 프로세스가 있습니다. 통계적으로 말하면 어느 시점에서든 할당된(또는 나중에 프로그램 실행 시 할당된) 모든 가상 페이지에 대해 집합적으로 매핑이 필요하지 않습니다.

엄격한 비오버커밋 시나리오에서는 가상 페이지를 할당할 때 가상 주소 페이지에서 물리적 RAM 페이지 프레임으로의 정적 매핑을 생성합니다. 많은 양의 RAM 페이지 프레임이 아무런 목적 없이 예약되므로 동시에 훨씬 적은 수의 프로그램을 실행할 수 있는 시스템이 됩니다.

나는 메모리를 과도하게 사용하는 것이 위험할 수 있으며 처리하기 어려운 메모리 부족 상황으로 이어질 수 있다는 사실을 부정하지 않습니다. 올바른 타협점을 찾는 것이 전부입니다.

답변2

당신은 마치 게으름이 문제로 간주되지 않는 것처럼 말합니다.프로그래밍 중 :).

많은 양의 소프트웨어는 단순성과 유지 관리성을 위해 최적화되어 있으며 메모리 부족 상태에서 살아남는 것을 매우 낮은 우선 순위로 처리합니다. 할당 실패는 일반적으로 치명적인 것으로 간주됩니다. 메모리를 소모하는 프로세스를 종료하면 사용 가능한 메모리가 없고 더 많은 메모리를 할당하거나 포괄적인 사전 할당의 복잡성 없이 시스템이 진행할 수 없는 상황을 피할 수 있습니다.

할당을 확인하고 종료하는 것과 확인하지 않고 충돌하는 것 사이의 차이가 얼마나 미묘합니까? malloc()이 성공했는지 실패했는지 확인하지 않는 프로그래머를 남용한다고 비난하는 것은 불공평합니다.

할당이 실패하더라도 "올바르게" 계속 작동한다고 신뢰할 수 있는 소프트웨어는 소수에 불과합니다. 커널은 일반적으로 생존할 것으로 예상됩니다. sqlite에는잘 알려진 강력한 테스트여기에는 특히 다양한 소형 임베디드 시스템을 지원하도록 설계되었기 때문에 메모리 부족 테스트가 포함됩니다.

정상 작동에서는 사용되지 않는 오류 경로로서 메모리 부족 조건을 올바르게 처리하면 유지 관리 및 테스트에 상당한 추가 부담이 부과됩니다.노력이 상응하는 이익을 얻지 못한다면 다른 곳에 더 수익성 있게 투자될 수 있습니다..

이런 일이 발생하면 가장 일반적인 실패 원인을 처리하기 위해 대규모 할당의 특수한 사례가 생성되는 경우가 많습니다.

하나 허용일정 금액과도하게 사용됨아마도 이 맥락에서 가장 잘 볼 수 있을 것입니다. 이는 Linux의 현재 기본 타협의 일부입니다.

커널 수준 오버커밋을 비활성화해야 한다는 점을 염두에 두십시오.교환당신이 사용하고 싶은 것보다 더 많은 것을 싫어하는 사람도 있습니다. 시간이 지남에 따라 RAM과 회전하는 하드 드라이브 사이의 속도 격차는 점점 더 넓어지기 때문에 시스템이 허용한 스왑 공간을 실제로 사용하는 경우 종종 "멈추기 시작"이라고 설명할 수 있습니다.

답변3

나는 Johan Myréen의 답변에 동의하고 찬성합니다. 그러나 문제를 이해하는 데 도움이 되는 추가 설명이 있습니다.

덜 사용되는 RAM과 가상 메모리를 저장하는 데 사용되는 디스크 공간인 스왑 영역을 혼동하고 있는 것 같습니다. 후자는 RAM 영역과 디스크 영역으로 구성된다.

프로세스가 가상 메모리를 예약하고 사용하고 있습니다. 그들은 그것이 어디에 저장되어 있는지 모릅니다. RAM에 존재하지 않는 일부 데이터에 액세스해야 하는 경우 커널이 데이터 페이지를 사용 가능하게 만드는 작업을 완료할 때까지 프로세스(또는 스레드)가 일시 중지됩니다.

RAM이 필요할 때 커널은 덜 사용되는 프로세스 페이지를 디스크 스왑 영역에 저장하여 일부 RAM을 확보합니다.

프로세스가 메모리를 예약하면(예: malloc 등) 오버커밋되지 않은 운영 체제는 가상 메모리의 사용되지 않은 부분을 사용할 수 없는 것으로 표시합니다. 이는 할당을 수행하는 프로세스가 실제로 해당 페이지에 액세스해야 할 때 예약된 페이지가 존재한다는 것을 보장한다는 의미입니다.

단점은 다른 프로세스에서 메모리를 사용할 수 없기 때문에 해당 프로세스가 페이지를 페이징하는 것을 방지하므로 이러한 프로세스가 비활성화되면 RAM이 낭비된다는 것입니다. 가장 나쁜 것은 예약의 합이 스왑 영역의 크기보다 큰 경우 데이터가 포함되어 있지 않더라도 예약과 일치하도록 RAM 페이지도 예약됩니다. RAM이 부족하기 때문에 이것은 매우 나쁜 상황입니다.둘 다쓸 수 없는그리고사용되지 않습니다. 마지막으로 최악의 시나리오는 더 이상 사용 가능한 가상 메모리(스왑 + 메모리)가 없어 대규모 예약을 수락할 수 없다는 것입니다. 예약 과정이 종종 중단됩니다.

반면에 Linux와 같이 과도하게 사용되는 운영 체제는 주어진 시간에 가상 메모리가 부족하지 않을 것이라고 확신합니다. 대부분의 메모리 예약을 허용하지만(다소 조정될 수 있는 비현실적인 메모리 예약은 허용하지 않음) 일반적으로 RAM 및 스왑 리소스의 활용도가 높아집니다.

이는 항공사가 좌석을 초과 예약하는 것과 유사합니다. 이로 인해 탑승률이 향상되지만 일부 승객은 만족하지 못할 수 있습니다. 항공사가 다른 항공편을 예약하고 보상을 받을 수 있기를 바라며 Linux는 더 무거운 승객을 비행기에서 내쫓을 뿐입니다.

대체로 Linux는 게으른 "최선의 노력" 방식으로 메모리를 예약하는 반면, 다른 여러 운영 체제에서는 예약을 보장합니다.

실제로 일어나는 일은 많은 가상 메모리를 사용하는 프로그램이 먼저 분기한 다음 실행하는 경우에만 오버커밋이 의미가 있다는 것입니다.

4GB의 RAM이 있고 그 중 3GB는 가상 메모리로, 4GB는 스왑용으로 사용할 수 있다고 가정해 보겠습니다. 4GB를 예약했지만 그 중 1GB만 사용하는 프로세스가 있습니다. 페이징이 없기 때문에 시스템 성능이 좋습니다. 오버커밋되지 않은 운영 체제에서는 포크 후에 4GB 이상의 가상 메모리를 예약해야 하고 3GB만 남으므로 프로세스를 포크할 수 없습니다.

Linux에서 이 포크(또는 복제) 시스템 호출은 성공적으로 완료되며(그러나 배후에서 치트가 발생함) 다음 실행(있는 경우) 후에 예약되었지만 사용되지 않은 4GB가 아무런 해를 끼치지 않고 해제됩니다.

답변4

살해 과정이 이상적일 수도 있다

다른 답변에서는 과도한 약속이 더 효과적인 방법에 대해 논의합니다. 또한 때로는 프로세스를 종료하는 것이 옳은 일이기도 합니다.

먼저 코드를 고려하십시오 while(1){malloc(1)}. 과도하게 사용하면 결국 OOM 킬러에 의해 죽게 됩니다. 오버커밋하지 않으면 사용 가능한 메모리를 모두 소모하여 시스템이 충돌하게 됩니다.

과잉 커밋이 없는 솔루션은 cgroup을 사용하여 메모리 양을 제한하는 것입니다. 그러나 이는 합리적인 기본값을 선택하는 과제를 남깁니다. 때로는 합리적인 기본값이 없는 경우도 있습니다. 일부 과학 작업은 일시 중지 문제를 해결하는 것만큼 어렵기 때문에 완료하는 데 얼마나 많은 메모리와 시간이 필요한지 알 수 없습니다. 과학적인 사용자가 사용 가능한 메모리의 모든 바이트를 안전하게 할당하도록 함으로써 더 중요한 프로세스에 메모리가 필요한 경우 OOM 킬러가 메모리를 중단시킬 것이라는 사실을 알면서 성공 가능성을 극대화할 수 있습니다.

관련 정보