C ++ 애플리케이션 성능 최적화 (오) - 운영 체제 메모리 관리

C ++ 애플리케이션 성능 최적화 (오) - 운영 체제 메모리 관리

첫째, 운영 체제 메모리 관리 소개

메모리에로드 할 때 오랜 시간 동안 컴퓨터 시스템에 메모리가 부족하고 귀중한 자원의 종류, 응용 프로그램 만 실행할 수 있습니다. 메모리 공간이 충분히 큰 경우 초기에 동시에 실행중인 응용 프로그램의 수는 심각한 응용 프로그램이 특정 시간에 실행해야 할 때 물리적 메모리보다 더 많은 응용 프로그램이 메모리를 실행하지 않습니다 제한됩니다. 현대 운영체제 (윈도우, 리눅스) 가상 메모리의 도입을 통해 메모리 관리 메모리가 부족 실행할 수 없습니다 응용 프로그램에서 문제를 해결합니다.
본질적으로, 가상 메모리가 완전히 메모리에로드하지 않을 때 실행하는 프로그램의 코드와 데이터를 확인하는 것입니다. 동작 동안, 코드를 실행할 때하는 것은 메모리에로드되어 있지 않은, 또는 액세스 데이터를 메모리에로드되어 있지 않은 가상 메모리 관리자는 동적 메모리, 하드 디스크로부터 적절한 코드 또는 데이터를로드. 정상적인 상황에서, 가상 메모리 관리자가 다가오는로드 코드 또는 데이터를위한 공간을 만들기 위해 하드 드라이브에 특정 코드 또는 데이터를 메모리의 대응하는 제 1 교체 될 것이다.
상기 코드의 실행에 대한 메모리 및 하드 드라이브의 데이터 전송은 매우 느리기 때문에 또한 데이터 코드 또는 액세스를 피하기 위해, 대체 알고리즘을 최적화 할 필요성 효율성 인자를 고려해야 전제의 정확한 동작을 보장하는데, 가상 메모리 관리자가 실행될 수 있기 때문에 단지 메모리의 교체 및 액세스 코드 또는 데이터가없는 긴 시간이 메모리에 상주하고있다. 가상 메모리 관리자는 또한 프로그램에 참여한다 디스크 IO의 수를 가능한 한 낮게 실행되도록 각 프로세스, 합리적인 숫자를 유지 메모리에 상주하고 프로세스 성과 동적 성능을 기반으로하여 조정의 데이터를 코딩 할 필요가 프로그램의 운영 성능을 향상시킬 수 있습니다.

두, 윈도우의 메모리 관리

1, 윈도우 가상 메모리 관리 시스템 소개

Win32에서 가상 메모리 관리자가 선형 프로세스 전용 4GB의 가상 어드레스 공간의 페이지에 기초하여 각각의 Win32 방법을 제공한다 (32)의 크기이다.
자신의 주소 공간에 대해 걱정하지 마십시오 각 프로세스는 자체 메모리 공간에만 액세스 할 수 있으며 다른 프로세스에 속하는 주소 공간에 액세스 할 수 있습니다 개인 프로세스가 다른 프로세스에 의해 부모와 자식 관계를 사용하여 같은 디버거로 (아들 프로세스 예외를 볼 수 있습니다 ) 디버깅 프로세스의 어드레스 공간에 액세스. 런타임 dll은 공정에 사용하고 자신의 주소 공간에 속하지 않았지만, 가상 주소 공간은 프로세스, DLL 전역 데이터를 속하고 열어 모든 프로세스의 가상 주소 공간의 응용 프로그램에서 메모리 DLL 함수 호출을 통해있는 상태.
가상 어드레스 공간은 페이지라는 단위를 복수로 분할 된 페이지이다 기초하여, 페이지 크기가 기본이 프로세서에 의해 결정되며, 86 프로세서 아키텍쳐의 페이지 크기를 킬로바이트이다. 페이지는 Win32 프로세스 가상 메모리 관리의 최소 단위이며, 대응하는 물리적 메모리는 복수의 페이지로 분할된다. 응용 프로그램 및 가상 메모리 주소 공간의 출시, 데이터 전송 또는 메모리와 디스크의 교체의 페이지의 가장 작은 단위입니다.
4기가바이트이 크기 범위의 프로세스가 0xFFFFFFFF로 행을 0x00000000로 될 수 있음을 의미 주소, Win32 프로세스 사용의 하부 영역에 2GB로 남아있을 것이며, 2GB의 높은 영역을 사용하도록 예약 시스템.
Win32에서가, 16가있을 수 있습니다 페이징 파일이라는 가상 메모리 하드 디스크 파일의 실현을 지원하기 위해 사용되는 메모리의 데이터를 저장하는 데 사용되는 페이징 파일은 가상 메모리 관리자로 대체됩니다. 데이터 페이징 파일을 다시 프로세스에 액세스 할 때 가상 메모리 관리자가 페이징 파일에서 프로세스가 제대로 액세스 할 수 메모리로 대체됩니다. 사용자는 메모리의 페이지로 대체 그렇게 할 때, (EXE 및 DLL 포함) 효율과 성능 공간의 이유로, 프로그램 코드가 수정되지 않습니다, 자신의 페이징 파일을 구성 할 수 있습니다 페이징에 기록되지 않습니다 파일하지만, 직접 포기. 다시 필요한 경우, 가상 메모리 관리자는 EXE를 찾을 수 또는 DLL은 프로그램 코드를 메모리에 저장 및 전송에서 파일을 직접. 또한, 동일한 공정에 포함 된 판독 전용 데이터 및 프로그램 코드 EXE 및 DLL 파일의 처리는, 상기 페이징 파일의 오픈 공간에 저장되지 않는다.
프로세스가 코드 또는 특정 데이터에 대한 액세스의 일부를 실행하지만 때하지 않을 때 페이지 오류 에러로 알려진 메모리에 코드 또는 데이터. 많은 이유, 메모리의 가장 일반적인 코드와 데이터를 가상 메모리 관리자 교체 페이지 오류는 가상 메모리 관리자는 코드에서 실행됩니다하거나 메모리로 전송하기 전에 데이터를 액세스하고. 메모리 교체는 크게 작업 개발을 단순화, 개발자들에게 투명합니다. 그러나 페이징 오류가 디스크 IO 크게 프로그램의 전반적인 성능을 줄일 페이징 오류 많은 수의 포함, 페이지 오류 오류 및 해결 방법에 대한 주요 이유를 알 필요가있다.

2 가상 메모리의 사용

Win32에서 할당 된 메모리는 예약과 최선을 다하고 두 단계로 나누어 져 있습니다. 따라서, 세 가지 상태의 프로세스 주소 공간의 가상 페이지 : 무료 무료, 따로 예약 및 설정은 최선을 다하고 제출합니다.
무료이 페이지는 아직 할당되지 않은, 새로운 메모리 할당 요청을 충족 할 수 있습니다.
가상 주소 공간으로부터 예약에 참조가되는 영역 (지역 페이지의 정수배)에서 메모리 공간이 새로운 메모리 할당 요청을 만족하기 위해 그릴 수를 따로 설정되지만 필요한 코드 예약이 메모리 섹션 나중에 사용하기. 예약은 물리적 메모리를 할당하지만, 데이터 구조합니다 (VAD, 기술자의 가상 어드레스)의 상태에 기재된 방법을 사용하여 가상 주소 공간을 추가하지 않은 경우, 기록 용 메모리 공간이 섹션은 보유하고있다. 직접 액세스 할 수있는 실제 물리적 메모리 할당, 따라서 예약 된 공간이 없기 때문에 준비 제도 이사회 (FRB) 조치는 상대적으로 신속하게, 예약 페이지에 대한 액세스는 메모리 액세스 위반이 발생할.
당신이 진짜 실제 메모리를 얻으려면, 제출, 메모리는 예약에 제출해야합니다. 제출 페이징 파일에서 공간을 열고 VAD에서 해당 항목을 수정합니다. 즉시 백업 대체 디스크 페이징 파일 공간에서 물리적 메모리에서 공간 만 개방 공간을 할당하지 않았다 또한 제출합니다. 코드 첫 번째 메모리에 데이터를 제출 방문, 시스템은 실제 물리적 메모리를 발견하지 않는 경우, 페이지 오류 동작을 발생합니다. 정말 실제 메모리를 할당합니다이 시간이, 그것은 또한 예약 된 동시에 제출 될 때까지 가상 메모리 관리자는 페이지 폴트를 처리합니다. 그래서 시간이 많이 걸리는 작업을보다 옆으로 설정, 디스크 페이징 파일에서 공간을 엽니 다 작업을 커밋합니다.
가상 주소는 Win32 가상 메모리 관리 수요 페이징 전략 아니 실제 물리적 메모리 할당은 적은 실제 액세스가 필요합니다. 첫째, 성능상의 이유로 수요 - 페이징 전략, 세그먼트를 완료하고 전반적인 성능을 개선하기 위해 노력할 것, 두 번째는 효율성을 이유로 공간, 실제로 액세스, Win32에서 항상 프로세스가 대부분의 데이터에 액세스하지 않는 생각 가정, 따라서 필요하지 않을 때 개방 공간 또는 순서 물리 메모리로의 교체는 저장 공간의 활용도를 향상시킬 수있다.
일부 프로그램 경우이 메모리에 대한 수요이지만, 즉시 모든 메모리를 필요로하지, 실행 성능 및 스토리지 효율성의 잠재 수요를 충족하기 위해 물리적 스토리지에서 한 번 열린 공간이 낭비이다. 수요가 가능성이 아니라으로 할당 된 메모리의 가장 가능성이 큰 부분은 결국 정말 사용하지 마십시오. 일회성이 응용 프로그램의 모든 물리적 메모리를 할당하는 경우는 크게 공간의 활용도를 줄일 수 있습니다.
그러나 그렇지 않은 경우 전체 예약 및 메커니즘을 투입하지만, 모든 요청, 시간에 서로 다른 지점에서 코드에 대한 빈번한 메모리에 대한 요구를 만족시키기 위해 메모리를 할당 할 필요가와 있기 때문에 극의 서로 다른 시점의 메모리에서 자신의 요청 격차 다른 코드 메모리의 요청이있을 수있는 경우, 가상 주소 공간이 좋은 지역 특성 사용 (예 순회 같이) 전체적인 것이다 액세스 연속하지 없기 때문에, RAM 메모리는 다른 시점에서 획득 자주 요청 코드를 발생할 수있다 이에 의해, 프로그램 실행을 감소 페이지 결함의 수를 증가시킨다.
예약 및 제출 Win32 프로그램은 예약 들어오는 MEM_RESERVE 매개 변수가 들어오는 MEM_COMMIT 매개 변수를 제출는 VirtualAlloc를 기능이 완료 될 때 사용합니다. 가상 메모리 기능을 이용 VirtualFree를 릴리스 파라미터에 따라 통과하고, 대응하는 기능에서 VirtualAlloc은 물리적 메모리 영역에 대응하는 가상 어드레스를 방출 할뿐만 아니라, 가상 어드레스 공간의 예약 상태에있을 수 있으며, 가상 주소 공간과 관련하여 함께 있고 릴리스는 가상 주소 영역은 자유 상태로 돌아갑니다.
스레드 스택과 힙 프로세스가 소유하여 구현하고 예약을 사용하여 두 단계 메커니즘의 Win32 시스템 스레드 스택을 다하고 다음과 같이 두 단계 메커니즘이 커밋 :
당신이 스레드 스택을 만들 때, 단지 가상 주소 공간을 별도로 설정, 기본값은 첫 번째 두가 처음 제출 (CreateThread 또는 링크 링크 옵션에 의해 수정 될 수 있습니다) 1M이다. 더 제출 페이지 스레드 스택의 필요성, 가상 메모리 관리자가 동적으로 1M의 상한에 도달 할 때까지, 그들의 요구를 충족하기 위해 다음 페이지에서 스레드의 가상 주소 영역을 제출할 때 중첩 된 함수를 호출하기 때문에. 슬로우됩니다 예약 영역의 크기 (기본 1M)의 상한에 도달 할 때, 가상 메모리 관리자는 예약 된 영역의 크기를 증가하지 않습니다,하지만 마지막 페이지를 제출할 때 스택 오버플로 예외를 발생, 오버 플로우 예외 스택 때 스레드 스택 사용할 수있는 공간이 프로그램은 정상적으로 실행할 수 있습니다. 프로그램이 마지막 페이지뿐만 아니라 저장 공간에 대한 지속적인 필요성이 시간이 상한을 초과하는 경우 스택 공간이 부족 계속 사용하면 직접 프로세스를 종료하게됩니다.
스택 오버 플로우가 전체 프로그램이 종료의 원인이 스레드를 방지하기 위해, 스택의 크기의 사용을 제어하려고합니다. 이러한 중첩 감소 기능으로, 재귀 함수의 사용을 줄이고, (힙 동적으로 확장되기 때문에, 힙의 오픈 공간에서 큰 물체를 저장하고, 스레드 스택 메모리를 사용할 수있는 기능에 큰 로컬 변수를 사용하지 않으려 고 영역은 스레드 생성시 수정되었습니다, 우리는) 스레드의 수명이 다할 때까지 확장 할 수 없습니다.
스레드 스택 오버 플로우를 방지하기 위해 전체 프로그램이 종료의 원인, 그것은 마지막 페이지를 제출할 때 발생 스레드 스택 오버 플로우, 캡처 오버 플로우 예외를 생성 할 수 예외 처리 스레드 신체 기능을 추가하고, 그에 따라 역할을 할 수 있습니다.

가상 메모리를 액세스 할 때도 3을 참조하면, 프로세스 흐름

가상 메모리 영역을 따로 제출 된하려면 가상 메모리 영역의 데이터에 준비 접근입니다. 다음과 같이 특정 메모리 액세스 프로세스가 프로그램 할 때 :
C ++ 애플리케이션 성능 최적화 (오) - 운영 체제 메모리 관리
데이터가 물리적 메모리에 이미있는 경우는, 가상 주소 관리자는 데이터의 가상 메모리 주소를 물리적 주소 점에 매핑해야합니다, 당신은 실제 메모리에있는 데이터를 액세스 할 수 있습니다. 이 경우 더 빨리, 디스크 IO를 포함하지 않습니다.
데이터 메모리는 단지의 기간에 처음으로 액세스 할 때이 실제 물리적 메모리 할당, 또는 이전에 방문한 된 액세스되는 데이터 없지만, 이후 가상 메모리 관리자 물리적 메모리로 대체 되었기 때문에, 제출, 이번에는 트리거 페이지 오류. 페이지 오류를 처리 할 가상 메모리 관리자, 가상 메모리 관리자는 먼저 데이터 (페이징 파일 백업 공간에 이미 백업 공간 EXE, DLL 코드 페이지인지를 감지하고 읽기 전용 데이터는 페이징 파일에없는, 그러나 EXE 백업 디스크 공간의 데이터에 대한 액세스가있는 경우, DLL 파일), 가상 메모리 관리자는 물리적 메모리의 오른쪽 페이지를 찾을 수 및 물리적 메모리에 디스크 교체에 백업 데이터를 저장합니다.
가상 메모리 관리자는 먼저 현재 실제 메모리의 무료 페이지가 있는지 여부를 확인, 가상 메모리 관리자는이 데이터 구조는 시스템 전체의 작동, Windows 시스템이 시작될 때 페이지 프레임 데이터베이스 (페이지 프레임 데이터베이스) 데이터 구조의 이름을 유지 또, 초기화 추적 각 물리적 메모리 페이지의 상태를 기록하는 데 사용되고, 모든 필요한 자유 페이지 함께 연결에 자유 페이지 목록이 직접 조회 자유 페이지 목록에있는 경우에는 자유 페이지로서 사용; 그렇지 않으면, 페이징 알고리즘에 따라 첫 번째 페이지를 선택한다. 페이지가 단지 이전 페이지에서 필요한 데이터를 포함하는 반면, 지방의 특성을 활용하기 위해, 페이징 가상 메모리 관리자에 전송되지 않을 때, 프로그램 효율을 개선하기 위해, 여러 페이지에 인접한 메모리로 전송한다. 메모리 페이지의 선거에, 다음 메모리로 전송 지난 이후이 페이지가 수정되지 않은 경우,이 페이지의 직접 사용이 페이지의 상태를 확인 (코드 페이지 및 직접 사용할 수있는 페이지 읽기 전용). 이 페이지가 수정 된 경우,이 페이지의 내용이 적절한 백업 페이지에서 디스크 페이징 파일에 기록하고 무료 페이지로이 페이지를 표시하는 필요. 이 시점에서 액세스 할 수에 대한 데이터를 저장하는 데 사용 무료 페이지가되어왔다. 가상 메모리 관리자는이 사용 허가 직접 무료 페이지 인 경우이 데이터 메모리와 단지 응용 프로그램을 처음 백업 디스크 페이징 파일에서 해당 페이지를 읽을 필요없이, 액세스 여부를 다시 감지; 그렇지 않은 경우에는 활성 페이지 페이지로 유휴 상태에서 다음이 여유 공간이 페이지를 읽어 적절한 백업 페이지에서 디스크 페이징 파일이 필요합니다.
이 경우, 데이터가 물리적 메모리 페이지에 이미, 가상 주소를 물리적 주소에 매핑 데이터에 액세스 할 수 있습니다.
사용자 정의 배열, 그냥 그 페이지의 경계 아래에이 배열,이 페이지의 다음 페이지가 무료 또는 상태 (비 제출을 위해 예약 할 때 실제 데이터 액세스, 상황은 정말, 같은 더 복잡한 것 실제 메모리). 프로그램 다운 실수 국경 간 접속이 배열은, 상기 제 페이지 폴트가 발생하면. 그런 다음 가상 메모리 관리자가 페이징 파일에 누락 된 페이지를 처리에서 오류를 감지, 그것은 소위 액세스 위반 (액세스 위반)하지 않습니다. 가상 메모리 주소 액세스 위반이 실제 물리적 메모리 주소에 해당하는 가상 메모리 주소를 액세스 위반이 직접 (충돌) 전체 프로세스가 종료의 원인이 없다는 것을, 지정된 주소가 제출되지 않은 액세스 할 수 있다는 것을 의미한다.
결과 포인터 국경 액세스는 서로 다른 런타임의 실제 상황, 배열이 같은 국경의 페이지마다 자신의 국경에없는 경우에만 잘못된 접근을하게됩니다이 시간에 (오해 또는 허위 진술, 오해 쓰기, 여전히에 따라 달라집니다 코드 만 실수로이 페이지의 코드 구현), 다른 데이터에 영향을 미칠 다른 곳에서 작성 실행되는 영향, 전체 프로세스 충돌이 발생하지 않습니다. 페이지, 포인터 값이 인접한 페이지 후 경계를 벗어날하지만,이 인접 페이지는 현재 국가의 제출도 경우 잘못된 접근이 여전히 어디에 배열이 정말 경계에 존재하더라도, 그것은 프로세스를 충돌 이어질하지 않습니다. 따라서, 같은 프로그램의 코드는 포인터 액세스 위반 오류의 배열이, 때로는하지, 실행할 때 가끔 충돌이 발생합니다.
인접한 페이지를 강제로 사용 가능한 페이지 페이지는, 각 국경 접근의 결과로, 액세스 위반이 발생하면서 마이크로 소프트는 포인터가 국경 접근을 감지하기에 pageheap 도구는 원칙 메모리 각 페이지의 경계에 위치하고 있습니다 필수 할당입니다 제공 개발 단계에서 국경 액세스 포인터 오류가 노출됩니다 오류의 발생없이 게시 된 버전에 숨겨진 포인터 국경 접근하고있다, 그래서 프로그램이 다운은, 최종 사용자 액세스 할 때까지 발견되지 않습니다.

4, 물리적 주소로 가상 주소 매핑

이미 후 물리적 메모리에 데이터에 대한 액세스를 보장, 당신은 첫 번째 물리적 주소로 가상 주소를 변환 할 데이터에 액세스 할 수있는 그 주소 매핑이 필요합니다.
는 Win32는 각각 4GB의 가상 주소 공간이 전용으로 처리하기 때문에, 각 프로세스의 주소 매핑을 달성하기 위해 계층 구조의 그 자신의 세트를 유지하고, 두 어드레스 매핑 테이블의 구조를 통해 달성된다. 첫 번째 층은, 페이지 디렉토리 테이블 (페이지 디렉토리) 1024에 4 바이트 단위로 실제로 메모리 페이지 (4킬로바이트 = 4096Byte)이며, 각각의 페이지 디렉토리 엔트리를 호출 (PDE, 페이지 디렉토리 엔트리) 상기 제 2 층은 테이블에 페이지 테이블 (페이지 테이블) 1024 개 페이지 테이블의 합계이다. 페이지 테이블에 해당하는 각각의 페이지 디렉토리 페이지 디렉토리 엔트리는, 각 페이지 테이블은 또한 메모리 페이지를 차지했다. 4 킬로바이트 페이지 테이블 (1024)는 또한, 페이지 테이블 엔트리 (PTE, 페이지 테이블 엔트리)라고 각각 4 바이트를 분할한다. 각 페이지 테이블 엔트리는 물리적 메모리의 페이지 프레임을 가리 킵니다.
C ++ 애플리케이션 성능 최적화 (오) - 운영 체제 메모리 관리
Win32에서 세 부분, 첫 번째 첨자 10 비트 페이지 디렉토리, 1024의 위치에 대한 페이지 디렉토리로 구성되어, 각각의 가상 어드레스는 32 비트 정수 값 인, 가상 주소 공간 4기가바이트 (32)의 크기를 제공한다 특정는, 특정 위치의 값에 따른 페이지 테이블의 페이지 테이블의 제 2 층을 볼 수 있으며, 페이지 테이블 인덱스, 페이지 테이블 (1024)에 위치하는 항목에 10 비트 연속하는 특정 물리적 페이지의 바이트 위치 (12)을 찾기위한 12 비트 바이트 인덱스 후 단지 페이지에 배치 될 수있다 물리적 메모리의 페이지가 가상 주소에 의해 표현되는 데이터를 포함하는 페이지가 있는지의 값을 찾을 수있다 바이트의 임의의 위치.
C ++ 애플리케이션 성능 최적화 (오) - 운영 체제 메모리 관리
포인터 값 0X2A8E317F, 물리적 주소 매핑 프로세스 가상 주소는 다음과 같이 프로그램에서 포인터 (가상 주소)에 액세스 가정 :
C ++ 애플리케이션 성능 최적화 (오) - 운영 체제 메모리 관리
페이지 디렉토리 엔트리는 4 바이트이기 때문에 0X2A8E317F 바이너리는, 제 1 위치의 세 부분으로 나누어 져 0,010,101,010,001,110 0,011,000,101,111,111, 10 비트 0010101010, 위치에 페이지 디렉토리 페이지 디렉토리 엔트리의 첫 번째 좌측 2 비트 0,010,101,010는 0X2A8 첨자는, 페이지 테이블에 페이지 디렉토리 엔트리 포인트와 대응하는 페이지 디렉토리 엔트리를 검색하여, (10) 1,010 1,000 (0X2A8)을 얻었다. 페이지 테이블의 10 비트, 즉 후속 포지셔닝 0,011,100,011 페이지 테이블 엔트리를 사용하여, 좌측 2 비트는 0X38B가 첨자로 페이지 테이블에 대응하는 페이지 테이블 엔트리를 검색하여, 0,011,100,011 11 1,000 1,100 (0X38B)이다. 페이지 테이블 엔트리 포인트는 실제 메모리를 찾을 수 있습니다. 마지막으로, 마지막 데이터의 12 비트, 즉 0001 0111 1111 (0X17F)으로, 즉,이 점에 대한 포인터, 데이터 페이지 내에 위치.
Win32에서 항상 그 실제 메모리 주소 매핑에서 데이터 및 가정했다. 이 페이지에 포함 된 데이터에 대한 마커와 페이지 테이블 엔트리가 물리적 메모리의 페이지에 취득 어드레스 맵핑을 수행하는 경우,이 비트를 검출하는 페이지 테이블 엔트리이며, 오류가없는 페이지를 슬로우 아니라면, 이 페이지 테이블 엔트리는 데이터가 다음 액세스 위반, 페이징 파일에하고, 그렇지 않은 경우 포함,이 페이지 테이블 엔트리는이 데이터 시트에서 발견 할 수있는 경우 페이징 파일에 있고, 페이징이 데이터 페이지 시작 위치 파일, 계속하려면 디스크의 물리적 메모리 주소 매핑 과정에서이 데이터 페이지를 옮겼다. 가상 개인 주소 각 프로세스를위한 공간 등을 구현하기 위해 각 프로세스는 다른 프로세스 페이지 디렉토리 페이지 디렉토리 항목 및 페이지 테이블의 페이지 테이블 엔트리는 다른에 대한 자신의 페이지 디렉토리 항목과 페이지 테이블 구조를 가지고 따라서 동일한 포인터 (가상 어드레스)를 물리적 어드레스로 매핑 다른 프로세스는 포인터 의미가 통과하는 다른 프로세스 사이이다 다르다있다.

5, 가상 메모리 공간 상태 레코드를 사용하여

Win32虚拟内存管理器使用另一个数据结构来记录和维护每个进程的4GB虚拟地址空间的使用及状态信息,即虚拟地址描述符树(VAD,Virtua Address Discriptor)。每一个进程都有自己的VAD集合,VAD集合被组织成一个自平衡二叉树,以提高查找的效率。另外由于只有预留或提交的内存块才会有VAD,自由的内存块没有VAD(即不在VAD树结构中的虚拟地址块就是自由的)。
(1)当程序申请一块新内存时,虚拟内存管理器执行访问VAD,找到两个相邻VAD,只要小的VAD的上限与大的VAD的下限之间的差值满足所申请的内存块的大小需求,即可使用二者之间的虚拟内存。
(2)当第一访问提交的内存时,虚拟内存管理器总是假定要访问的数据所在数据页已经在物理内存中,并进行虚拟地址到物理地址映射。当找到相应的页目录项后发现页目录项并没有指向一个合法的页表,虚拟内存管理器就会查找进程的VAD树,找到包含该地址的VAD,并根据VAD中的信息,比如内存块大小、范围,以及在调页文件中的起始位置,随需生成相应的页表项。然后从刚才发生缺页错误的位置继续进行地址映射。因此,一个虚拟内存页被提交时,除了在调页文件中开辟一个备份页外,不会生成指向它的页表项的页表,也不会填充指向它的页表项,更不会开辟真正的物理内存页,而是直到第一次访问提交页时才会随需地从VAD中取得包含该页的整个区域的信息,生成相应页表,并填充相应页的页表项。
(3)当能够访问预留的内存时,虚拟地址管理器进行虚拟地址到物理地址的映射,找到相应的页目录项后发现页目录项并没有指向一个合法的页表,虚拟地址管理器就会查找进程的VAD树,找到包含该地址的VAD,此时发现此段内存块只是预留的,而没有提交,即没有对应物理内存,直接抛出访问违例,进程退出。
(4)当访问自由的内存时,虚拟地址内存管理器进行虚拟地址到物理地址的映射,找到相应的页目录项后发现页目录项并没有指向一个合法的页表,虚拟地址管理器就会查找进程的VAD树,发现并没有VAD包含此虚拟地址,发现此虚拟地址所在的虚拟内存页是自由状态,直接抛出访问违例,进程退出。

6、进程工作集

因为频繁的调页操作引起的磁盘IO会大大降低程序的运行效率,因此对每一个进程,虚拟内存管理器都会将一定量的内存页驻留在物理内存中,并跟踪其执行的性能指标,并动态调整驻留的内存页数量。Win32中驻留在物理内存中的内存页称为进程的工作集(working set),进程的工作集可以通过任务管理器查看,内存使用列即为工作集大小。
工作集是会动态变化的,进程初始时只有很少的代码页和数据页被调入物理内存。当执行到未被调入内存的代码或访问到尚未调入内存的数据时,相应代码页或数据页会被调入物理内存,工作集也会随之增加。但工作集不能无限增加,系统为每个进程设定了一个最小工作集和最大工作集,当工作集达到最大工作集大小,进程需要再次调入新页到物理内存时,虚拟内存管理器会架构原来工作集中某些内存页先置换出物理内存,然后再将需要调入的新页调入内存。
因为工作集的页驻留在物理内存中,对工作集页的访问不会涉及磁盘IO,因此速度非常快。如果访问的代码或数据不在工作集中,会引发额外的磁盘IO,从而降低程序的执行效率。极端情况下会出现所谓的颠簸或抖动(thrashing),即程序的大部分执行时间都花在调页操作上,而不是执行代码上。
虚拟内存管理器在调页时,不仅仅只是调入需要的页,同时还将其附近的页一起调入内存中,对于开发人员,如果要提高程序的运行效率需要考虑如下:
(1)对代码李硕,尽量编写紧凑代码,最理想情形是工作集不会达到最大阈值,在每次调入新页时,就不需要置换已经载入的内存页,因为根据locality特性,以前执行的代码和访问的数据在后面有很大可能会被再次执行好访问,因此程序执行时,缺页错误会大大降低,即减少磁盘IO。从进程任务管理器也可以查看一个进程从开始时到当前时刻共发生的缺页错误次数。即使不能达到理想情形,紧凑的代码往往意味着接下来执行的代码更大可能就在当前页或相邻页。根据时间locality特性,程序80%的时间花费在20%代码上,如果能将耗时的20%代码尽量紧凑且排在一起,会大大提高程序的整体性能。
(2)对数据来说,尽量将那些会一起访问的数据(如链表)放在一起,当访问数据时,数据在同一页或相邻页,只需要一次调页操作就可以完成。如果数据分散在分散在多个页(多个页不相邻),每次对数据的整体访问都会引发大量的缺页错误,从而降低性能。利用Win32提供的预留和提交两步机制,可以为一同访问的数据预留一大块空间,此时并没有分配实际存储空间,而是在后续执行过程中生成数据时格局需要提交内存,既不浪费存储空间(物理内存和磁盘的调页文件存储空间),又能利用locality特性。

三、Linux内存管理

1、Linux内存管理机制简介

Linux的内存管理主要分为两部分,一部分负责物理内存的申请与释放,物理内存的申请与释放的最小单位为页,在IA32中,页的大小为4KB;另一部分负责处理虚拟内存,虚拟内存的主要操作包括虚拟地址空间与物理地址空间的映射,物理内存页与磁盘页之间的置换等。

2、Linux进程的内存布局

一个32位Linux进程的地址空间为4GB,其中高位1GB,即0XC0000000--0XFFFFFFFF,为内核空间,低位3GB,即0X00000000--0XBFFFFFFF为用户地址空间。用户地址空间进一步被分为程序代码区、数据区(包括初始化数据区DATA和未初始化数据区BSS)、堆和栈。程序代码区占据最低端,往上是初始化数据区DATA和未初始化数据区BSS。代码区存放应用程序的机器代码,运行过程中代码不能修改,因此代码区内存为只读,且大小固定。数据区中存放应用程序的全局数据,静态数据和常量字符串,数据区大小也是固定的。
堆从未初始化数据区开始,向上端动态增长,增长过程中虚拟地址值变大;栈从高位地址开始,向下动态增长,虚拟地址值变小。
堆是应用程序在运行过程中动态申请的内存空间,如通过malloc/new动态生成对象或开辟内存空间时,最终会调用系统调用brk来动态调整数据区的大小。当申请的动态内存区域使用完毕,需要开发者明确使用相应的free/delete对申请的动态内存空间进行释放,free/delete最终也会使用brk系统调用调整数据区的大小。
栈是用来存放函数的传入参数、临时变量以及返回地址等数据,不需要通过malloc/new开辟空间,栈的增长与缩减是因为函数的调用与返回,不需要开发人员操作,没有内存泄漏的危险。
初始化数据区存放的是编译期就能够知道由程序设定初始值的全局变量及静态变量等,其初始值必须保存在最终生成的二进制文件中,并且在程序运行时会原封不动地将此区域映射到进程的初始化数据区。如果一个全局变量或静态变量在源代码中没有被赋初始值,在程序启动后,在第一次被赋值前,其初始值为0,本质上是有初始值的,其初始值为0。但当最终生成二进制文件时,未初始化数据区不会占据对应变量总大小的区域,而是只用一个值进行标识其未初始化数据区的总大小。如一个程序的代码指令有100KB,所有初始化数据总大小为100KB,所有未初始化数据总大小为150KB,则在最终生成的二进制文件中代码区有100KB,接着是100KB的初始化数据区,然后是4字节的大小空间,用于标记未初始化数据区大小,其值为150X1024,用于节省磁盘空间。但在进程虚拟地址空间中,对应未初始化数据区的大小必须是150KB,因为在程序运行时,程序必须真正能够访问到变量中的每一个,即当程序启动时,当检测到二进制文件中未初始化数据区的值为150X1024,则系统会开辟出150KB大小的区域作为进程的未初始化数据区并同时使用0对其进行初始化。

3、Linux物理内存管理

物理内存是用来存放代码指令与供代码指令操作的数据的最终场所,因此物理内存的管理是内存管理系统极其重要的任务。Linux使用页分配器(page allocator)来管理物理内存,页分配器负责分配和回收所有的物理内存页(物理内存的分配与回收的最小单位为4KB大小的页)。
页分配器的核心算法称为兄弟堆算法(buddy-heap algorithm),算法思想是每个物理内存区域都会有一个与之相邻的所谓兄弟区域,当两个区域被回收后,会被合并成为一个区域。如果被合并区域的相邻区域也被回收后,会被进一步合并为更大的区域。当有物理内存请求到来时,页分配器会首先检测是否有大小与之一致的区域。如果有,直接使用找到的匹配区域满足请求;如果没有,则找到更大的一个区域,并继续划分,直到分出的区域能够满足请求。为了配合兄弟堆算法,必须有链表来记录自由的物理内存区域,对于每个相同大小的自由区域,会有一个链表将其连接,每种大小的区域都会有一个链表对其进行管理。自由区域的大小都是2的幂。
当有一个8KB大小的内存请求到来,当前最小可供分配的区域为64KB,此时64KB会被划分为两个32KB,继而将低位的32KB继续划分为两个16KB大小的区域,再将最低位的16KB大小区域划分为两个8KB大小的区域,然后分配高位的8KB区域满足请求。

4、Linux虚拟内存管理

가상 메모리 관리자의 주요 작업은 백업 스토리지와 같은 디스크 파일이있는 경우, 영역이 사용 된 같은 어떤으로 응용 프로그램 사용 정보 (지도)의 가상 주소 공간을 유지하는 것입니다. 그렇다면, 디스크의 각 영역에 해당하는 어떤 영역에서 또 다른 중요한 기능은 물리적 메모리로 전송되지 않은 등의 특정 데이터에 액세스 할 수있는 프로그램과 페이징이다, 가상 메모리 관리자는 위치 데이터에 대한 책임, 물리적 메모리로 교체 . 이 때 물리적 메모리 페이지뿐만 아니라 밖으로 교체하기 전에 물리적 메모리의 일부 페이지에, 더 자유가없는 경우.
응용 프로그램의 가상 주소 공간 사용 정보 데이터 구조를 유지하는 데 사용 vm_area_struct입니다. 숫자 32 vm_area_struct,리스트로 연결되는 경우보다 더 많은 경우에 프로세스의 가상 어드레스 공간을 설명 vm_area_struct 각 구조는, 영역이 할당되고, 32 개 이상은 모두가 vm_area_struct로 구성 될 때 자기 균형 검색 속도를 도움이 될 것입니다 이진 트리를. 프로그램 포인터를 통해 데이터에 액세스 할 때 포인터가 어드레스 포인터에 의해 표시되는 모든 영역 대표가 상기 포인터, 즉, 부정 액세스를 할당되지 않은 것으로 판정되는 vm_area_struct 내에 발견되지 않는 경우, 시스템은 vm_area_struct 트리 쿼리.

5, 가상 주소를 물리적 주소에 매핑된다

포인터 위해 본질적 가상 어드레스 값이고, 따라서 가상 어드레스의 값이 물리적 어드레스 값으로 변환되어야하기 때문에, 프로그램에 대한 포인터를 통해 데이터에 액세스 할 때 진정한 액세스 데이터는 그것이 참조하는 어느.
리눅스는 물리적 주소에 매핑 3 계층 전략 매핑 된 가상 주소를 사용합니다. 리눅스와 윈도우 따라서 동일 IA32 아키텍처, 중간 계층을 사용하지 않는 윈도우, 더 많은 중동 층,와 비교.

추천

출처blog.51cto.com/9291927/2406548