SlideShare a Scribd company logo
1 of 32
구본탁
• 메모리 맵 파일 기능은 가상 메모리처럼 주소공간을 예약하고 예약된 영역에 물리적 저장소를 커밋하는 제공한다.
• 시스템 페이징 파일을 사용하는 대신 디스크 상에 존재하는 파일을 물리적 저장소로 사용한다.
• 이러한 파일이 일단 영역에 매핑되면 마치 메모리에 파일의 내용이 모드 로드된 것처럼 사용할 수 있다.
• 시스템은 exe나 DLL 파일을 읽고 수행하기 위해 메모리 맵 파일을 사용한다.
이로인해 시스템은 페이징 파일의 크기를 일정하게 유지할 수 있으며, 애플리케이션의 시작시간도 일정하게
유지할 수 있다.
• 디스크에 있는 데이터에 접근하기 위해 메모리 맵 파일을 사용할 수 있다. 메모리 맵 파일을 사용하면 파일에 대한
I/O작업이나 파일의 내용에 대한 버퍼링을 자동적으로 수행해 준다.
• 동일한 머신에서 수행중인 다수의 프로세스 간에 데이터를 공유하기 위해서 메모리 맵 파일을 사용할 수도 있다.
윈도우는 프로세스들 사이에 데이터를 전달하는 다양한 방법들을 제공하고 있지만 내부적으로는 모두 메모리 맵
파일을 사용하여 구현되어있으며, 실제로 메모리 맵 파일을 사용하는 것이 단일의 머신에서 프로세스 간에
데이터를 전달하는 가장 효과적인 방법이다.
1. 실행 파일과 DLL 파일에 대한 메모리 맵
CreateProcess를 호출하면 시스템은 다음과 같은 절차를 순차적으로 수행한다.
1. 시스템은 CreateProcess 함수의 매개변수로 전달된 exe파일을 찾는다. 만약 존재하지 않으면 프로세스는
생성되지 않으며, CreateProcess 함수는 false를 반환하게 된다.
2. 시스템은 새로운 프로세스 커널 오브젝트를 생성한다.
3. 시스템은 새로운 프로세스를 위한 전용의 주소 공간을 생성한다.
4. 시스템은 exe파일을 수용할 수 있을 만큼의 충분한 영역을 주소 공간 내에 예약한다. Exe파일이 선호하는
시작 주소는 일반덕으로 exe파일 내에 기록되어 있으며, 시작 주소는 0x00400000이다.(기본 시작 주소는
64비트 윈도우에서 64비트 애플리케이션을 수행할 때에는 달라질 수 있다.) 이 값은 애플리케이션을
링크할 때 /BASE 링커 옵션을 이용하여 변경이 가능하다.
5. 시스템은 예약된 영역에 사용할 물리적 저장소로 시스템의 페이징 파일 대신 exe파일 자체를 지정한다.
1. 실행 파일과 DLL 파일에 대한 메모리 맵
정적 데이터는 실행 파일과 DLL의 여러 인스턴스들 사이에 공유되지 않는다.
이미 수행중인 애플리케이션을 다시 한번 수행하면, 시스템은 앞서 수행되었던 실행 파일 이미지를 가리키는
파일 매핑 오브젝트를 투영하는 새로운 메모리 맵 뷰에 대한 열기 작업을 수행하고,
새로운 프로세스 오브젝트와 새로운 스레드 오브젝트를 생성한 후, 각 오브젝트별로 새로운 프로세스 ID와
스레드ID를 부여한다.
메모리 맵 파일을 이용하면 동일 애플리케이션의 인스턴스가 여러 번 수행될 경우 램 상에 이미 로드된 코드와
데이터를 공유하게 된다.
하지만 이러한 동작 방식에는 문제를 유발할 소지가 있다. 프로세스들은 순차적으로 펼쳐진 메모리
주소공간을 이용하고 있다. 프로그램을 컴파일하고 링크하게 되면 코드와 데이터는 단일의 파일로 구성되게
된다. 물론 데이터와 코드가 서로 다른 영역으로 분리되어 있긴 하지만, 엄연히 말해 단일의 exe파일 내에 함께
내장되어 있는 것은 사실이다.
1. 실행 파일과 DLL 파일에 대한 메모리 맵
실제로 어떻게 가상메모리에 로드되고 애플리케이션의 주소공간에 매핑 되는지를 나타낸 것이다.
1. 실행 파일과 DLL 파일에 대한 메모리 맵
애플리케이션의 두 번째 인스턴스가 수행되면 시스템은 가상 메모리에 로드되어 있는
코드와 데이터를 두 번째 인스턴스의 주소 공간에 매핑한다.
1. 실행 파일과 DLL 파일에 대한 메모리 맵
아래 그림은 애플리케이션의 첫 번째 인스턴스가 데이터 페이지 2번에 저장되어 있는
전역변수의 내용을 변경하려고 시도하였을 때의 모습을 그림으로 나타낸 것이다.
1. 실행 파일과 DLL 파일에 대한 메모리 맵
실행 파일과 DLL의 여러 인스턴스들 사이에 정적 데이터 공유하기
exe나 DLL 파일 내에 전역으로 선언된 정적 데이터들은 파일들이 서로 다른 여러 프로세스들의 주
소공간에 각기 매핑되더라도 기본적으로 그 내용을 공유하지 않는다. 하지만 때로는 exe나 DLL 파
일이 서로 다른 프로세스들의 주소 공간 상에 여러 번 매핑된다 하더라도 변수의 내용을 공유할 수
있으면 유용할 때가 있다.
예를 면, 윈도우는 통일 애플리케이션이 이전에 수행된 적이 있는지를 간단하게 확인할 수 있는 방법이
없다. 만일 전역변수가 모든 인스턴스들 사이에서 공유될 수 있다면 이를 통해 동일 애플리케이션의 반복
수행 횟수를 저장해 두어 동일 애플리케이션이 이전에 이미 수행 중인지의 여부를 쉽게 확인할 수 있다.
즉 사용자가 애플리케이션의 새로운 인스턴스를 수행하였을 때 먼저 전역변수의 내용을 확인하고 이 값이
1 일 경우통일 애플리케이션이 이미 수행 중이며, 자신이 두 번째 인스턴스임을 알 수 있다. 이 경우
사용자에게 이 애플리케이션은 유일하게 한 번만 수행할 수 있음을 알려주고 종료할 수도 있다.
이렇듯 exe와 DLL의 모든 인스턴스들 사이에서 변수를 공유하는 기법은 앞으로 논의할 섹션 기법
을 이용함으로써 가능하다. 하지만 이에 대해 자세히 살펴보기 전에 조금의 배경 지식이 필요하다.
모든 exe와 DLL 파일 이미지는 섹션들의 집합으로 구성되어 있다. 편의를 위해 표준 섹션들은 점으
로 시작하는 이름을 가지고 있다. 예를 들어 프로그램을 컴파일하게 되면 컴파일러는 자신이 생성한
모든 코드를 .text라는 이름의 섹션 내에 배치한다. 또한 초기화되지 않은 데이터는 .bss 섹션에, 초
기화된 데이터는 .data 섹션에 각각 나누어 배치한다.
1. 실행 파일과 DLL 파일에 대한 메모리 맵
실행 파일과 DLL의 여러 인스턴스들 사이에 정적 데이터 공유하기
1. 실행 파일과 DLL 파일에 대한 메모리 맵
컴파일러나 링커가 생성해 주는 표준 섹션 이름 외에도 소스 코드에 다음과
같은 지시어를 사용하여 자신만의 섹션 이름을 지정할 수 있다
예를 들어 Shared라는 이름의 섹션을 만들고 그 안에 LONG 값을 저장하고 싶다면
다음과 같이 코드를 작성하면 된다.
컴파일러가 이 코드를 컴파일하게 되면 Shared라는 이름의 새로운 섹션을 생성하고 pragma 이후
에 나타낸 모든 초기화된 데이터 변수를 해당 섹션 안에 추가한다.
1. 실행 파일과 DLL 파일에 대한 메모리 맵
마이크로소프트 Visual C++ 컴파일러는
allocate라는 선언 지정자 declaration
specifier를 제공하여 초기화되지 않은
데이터의 경우에도 사용자가 지정한
섹션에 내용을 추가할 수 있도록 해
주고 있다.
1. 실행 파일과 DLL 파일에 대한 메모리 맵
Allocate 선언 지정자가 정상적으로 동작하도록 하려면
항상 해당 섹션이 먼저 생성되어 있어야 한다. 따라서
위 코드에서 #pragma data_seg 행들을 제거해 버리면
코드는 정상적으로 컴파일 되지 않을 것이다.
새로운 섹션을 구성하고, 그 섹션에 변수들을 추가하는
대부분의 경우는 exe와 DLL 파일이 다수의
프로세스 공간에 여러 번 매핑 되더라도 해당 변수를
공유할 수 있도록 하기 위함일 것이다. 이렇게
새로운 섹션에 여러 개의 변수를 삽입해 두면 여러 개의
인스턴스 사이에 공유할 수 있는 일련의 데이터 그룹을
구성할 수 있게 된다.
이러한 데이터 그룹들은 exe 나 DLL 파일들이 새롭게
생성된 프로세스의 주소공간에 추가적으로
매핑되더라도 변수에 대한 새로운 인스턴스를 생성하지
않고 기존의 값을 공유하게 된다.
1. 실행 파일과 DLL 파일에 대한 메모리 맵
단순히 컴파일러에게 몇몇 변수들을 고유의 섹션 내에 배치하도록 하는 것만으로
변수를 공유할 수 있는 것은아니다.
추가적으로 링크단계에서 링커에게 특정 섹션은 공유되어야 한다는 사실을 반드시 알
려주어야만 하는데 링커스위치 중 / SECTION을 이용함으로써 이러한 작업을 수행할
수 있다.
콜론 기호 이후에는 섹션의 이름과 해당 섹션에 적용할 특성 정보를 지정하면 된다.
Shared 섹션의 특성을 변경해야 하므로 다음과 같이 링커 스위치를 사용하면 된다.
1. 실행 파일과 DLL 파일에 대한 메모리 맵
쉽표 기호 이후에는 필요한 특성 정보를 나열하면 되는데 R은 읽기, W는 쓰기, E는
실행, S는 공유를 의미한다. 위 스위치의 경우 Shared 섹션 내의 데이터는 읽고
쓰는 것이 가능한 공유 섹션임을 지정하게 된다.
만일 한 개 이상의 섹션에 대해 특성 정보를 변경하고 싶은 경우라면 /SECTION
스위치를 여러 번 사용하면 된다.
이러한 방법 외에도 소스코드 내에 다음과 같이 링커 스위치를 포함시킬 수도 있다.
위와 같은 행을 포함시키면 컴파일러는 obj 파일 내에 “ .drectve'’ 라는 이름의 특수한 섹션을 생성하
여 그 안에 지정된 문자열을 포함시키게 된다.
링커는 .obj 모률을 결합할 때 .obj 모듈 내의
“ drectve" 섹션 내의 문자열을 확인하고, 해당 문자열이 마치 링커의 명령행 인자로 전달된 것처럼
링크를 수행하게 된다.
1. 실행 파일과 DLL 파일에 대한 메모리 맵
이와 같이 사용자가 임의로 공유 섹션을 만들 수 있음에도 불구하고,
마이크로소프트는 두 가지 이유로 인해 공유 섹션을 사용하지 말 것을 권고한다.
• 공유되는 메모리를 사용하게 되면 잠재적으로 보안에 취약해질 가능성이 있다.
• 공유변수를 사용하게 되면 특정 애플리케이션 내에서 발생하는 에러가 다른
애플리케이션에 직접적인 영향을 줄 수 있다.
• 실제로 애플리케이션 내에서 공유변수에 대해 임의로 접근하는 것을 막을 수 있는
방법이 존재하지 않는다.
2. 메모리 맵 데이터 파일
운영체제는 프로세스의 주소공간에 데이터 파일을 매핑할 수 있기 때문에 크기가 큰
데이터 스트림을 편리하게 다룰 수 있다.
방법 1: 한개의 파일, 한개의 버퍼
첫 번째 방법은 이론적으로 가장 간단한 방법으로 파일 전체의 내용을 모두 읽을 수 있는 충분한 크
기의 메모리 블록을 할당하는 방법이다.
파일을 열고 메모리로 그 내용을 모두 읽어온 뒤 파일을 닫는다.
이후 메모리에 파일의 내용이 모두 담겨 있으므로 첫 번째 바이트와 마지막 바이트를 교환하
고 , 두 번째 바이트와 마지막에서 두 번째 바이트를 교환하는 식으로 반복한다.
파일의 중간에 도달할 때까지 이러한 교환 작업을 반복한 이후 파일을 다시 열고 메모리 블록의 내용을 파
일로 덮어쓴다.
2. 메모리 맵 데이터 파일
방법 2: 두 개의 파일, 한 개의 버퍼
두 번째 방법은 기존 파일을 여는 것과 동시에 파일 크기가 0 인 파일을 새로 생성하는 방법이다.
내부적으로 8KB 정도의 작은 버퍼를 할당하고 기존 파일의 가장 끝으로부터 8KB만큼 떨어진 곳으로
이동한 후 파일의 마지막 8KB를 버퍼로 읽어 들인다.
이제 버퍼의 내용을 뒤집고, 새롭게 생성한 파일에 그 내용을 저장한다.
처리 과정은 파일 포인터 이동, 읽기, 뒤집기, 쓰기 순으로 반복되며, 이러한 과정을 기존 파일의 시작에
다다를 때까지 반복한다. 어려운 작업이 아니긴 하지만 기존 파일의 크기가 8KB의 배수가 아닌 경우
특별한 처리가 필요하다. 기존 파일에 대한 처리가 모두 완료되면, 두 파일을 닫고 기존 파일을 삭제한다.
2. 메모리 맵 데이터 파일
방법 3: 한 개의 파일, 두 개의 버퍼
방법은 두 개의 8KB 크기의 버퍼를 할당하는 것으로 시작한다.
프로그램은 파일로부터 가장 앞쪽의 8KB와 가장 뒤쪽의 8KB를 각각 서로 다른 버퍼로 읽어 들인다.
이후 각 버퍼의 내용을 뒤집고 파일의 앞쪽 내용을 담아두었던 버퍼의 내용을 파일의 뒤쪽에, 파일의 뒤쪽
내용을 담아두었던 버퍼의 내용을 파일의 앞쪽에 덮어쓴다.
이러한 작업을 파일 전체 내용에 대해 반복한다. 이 방법은 파일의 크기가 16KB 의 배수가 아니어서 8KB
의 버퍼로 읽어올 경우 내용이 겹치는 경우에 특별한 처리가 필요하다.
이러한 고려사항을 처리하기 위해서는 두 번째 방법의 경우에 비해 상당히 복잡한 코드를 필요로 한다.
2. 메모리 맵 데이터 파일
방법 4: 한 개의 파일, 버퍼는 사용하지 않음
메모리 맵 파일을 이용하여 파일의 내용을 뒤집기 위해서는 파일을 열고 가상 주소 공간 상에 영역을
예약한 뒤 파일의 첫 번째 바이트와 예약된 영역의 첫 번째 위치를 매핑시킨다.
이후 가상 메모리 주소에 접근하게 되면 이는 마치 파일의 내용에 직접적으로 접근하는 것과 같은 효과를
가져온다.
텍스트 파일의 내용이 0으로 끝나는 경우 파일의 내용이 모두 메모리에 있는 것과 같이 C 런타임
라이브러리에서 제공하는 _tcsrev 함수를 호출하여 파일의 내용을 모두 뒤집을 수 있다.
3. 메모리 맵 파일 사용하기.
메모리 맵 파일을 사용하려면 다음의 세가지 단계를 수행해야 한다.
1. 메모리 맵 파일로 사용할 디스크 상의 파일을 나타내는 파일 커널 오브젝트를
생성하거나 연다.
2. 파일의 크기와 파일의 접근 방식을 고려하여 파일 매핑 커널 오브젝트를 생성한다.
3. 프로세스의 주소 공간 상에 파일 매 핑 오브젝트의 전체나 일부를 매핑시킨다.
메모리 맵 파일을 더 이상 허용할 필요가 없다면 다음의 세 가지 단계를 수행해야 한다.
1. 프로세스의 주소 공간으로부터 파일 매핑 오브젝트의 매핑을 해제한다.
2. 파일 매핑 커널 오브젝트를 닫는다.
3. 파일 커널 오브젝트를 닫는다.
614p 참고
4. 메모리 맵 파일을 이용하여 큰 파일 처리하기
8GB 크기의 파일을 32 비트 주소 공간을 통해 접근하는. 아래에 몇 가지 단계를 통해
파일 내에 존재하는 0의 개수를 세어보는 루틴.
5. 메모리 맵 파일과 일관성
사용자는 특정 파일 내의 동일 데이터에 대해 여러 개의 뷰를 생성하여 프로세스의 주소 공간에 매핑
할 수 있다. 예를 들어 파일의 앞쪽으로부터 10KB의 내용을 특정 뷰에 매핑한 후, 또 다른 뷰에 파일
의 앞쪽으로부터 4KB 의 내용을 매핑할 수 있다. 단일의 파일 매핑 오브젝트를 여러 개의 뷰를 이용
하여 매핑하는 경우에는 파일 내의 데이터에 대한 일관성이 유지된다.
즉 애플리케이션이 특정 뷰를 통해 그 내용을 변경하게 되면 다른 뷰에도 변경사항이 모두 반영된다.
다른 프로세스가 이미 매핑하고 있는 파일이라 하더라도 새로운 프로세스는 추가적으로 CreateFile
함수를 호출하여 열기 작업을 수행할 수 있으며 ReadFile과 WriteFile 함수를 이용하여 파일에 대한
읽기와 쓰기 작업을 수행할 수 있다.
물론 프로세스가 이러한 함수들을 호출하는 이유는 파일로부터 메모리 버퍼로 데이터를 가져오거나
메모리 버퍼에 존재하는 데이터를 파일로 쓰기 위함이다.
이러한 메모리 버퍼는 새로 생성한 프로세스가 생성한 것이며 파일 매핑을 위해 사용되는 메모리는
아닐 것이다. 그런데 이처럼 두 개의 프로세스가 동시에 동일한 파일에 대해 열기 작업을 수행한 경
우 문제가 발생할 소지가 있다.
파일 매핑 오브젝트를 이용하여 파일을 사용하는 프로세스가 있는 경우에도 별도의 프로세스가
ReadFile을 이용하여 동일한 파일의 데이터를 읽고, 그 내용을 수정하고, WriteFile을 이용하여 파일의
내용을 수정할 수 있다. 이러한 이유로 파일을 메모리에 매핑하여 사용하길 원한다면 CreateFile을 호출할
때 dwShareMode 매개변수로 0을 지정할 것을 권고한다. 이렇게 함으로써 시용자가 파일에 대한 배타적인
접근 권한을 요구한다는 사실을 시스템에 알려줄 수 있으며, 이 경우 다른 프로세스는 해당 파일을
추가적으로 열지 못하기 때문에 일관성 문제를 유발하지 않는다.
6. 메모리 맵 파일의 시작 주소 지정하기
VirtualAlloc 함수를 사용할 때 예약할 주소 공간의 시작 주소를 전달할 수 있는 것과 같이
MapViewOfFile함수 대신 MapViewOfFileEx 함수를 사용하면 매핑할 시작 주소를 지정할 수 있다.
7. 메모리 맵 파일의 세부 구현사항
프로세스의 주소 공간을 통해 파일 데이터에 접근하려면 MapViewOfFile 함수를 먼저 호출해 주어
야 한다.
프로세스가 MapViewOfFile 함수를 호출하면 시스템은 해당 함수를 호출한 프로세스의 주소 공간
내에 뷰를 매핑할 영역을 예약한다.
따라서 다른 프로세스는 이러한 뷰를 볼 수 없다.
만일 다른 프로세스가 동일 파일 매핑 오브젝트를 이용하여 파일 데이터에 접근하고자 한다면
MapViewOfFile함수를 재호출하여 자신의 프로세스 주소 공간 내에 영역을 확보해야만 한다.
특정 프로세스에서 Map ViewOfFile 함수를 호출하였을 때 반환되는 메모리 주소는 다른 프로세스
에서 Map ViewOfFile 함수를 호출하였을 때 반환되는 주소외는 다르다는 점에 특히 주의할 필요가
있다.
이러한 특성은 여러 개의 프로세스가 동일 파일 오브젝트를 이용하여 뷰를 매핑한다 하더라도
동일하게적용된다.
7. 메모리 맵 파일의 세부 구현사항
다른 형태의 세부 구현사항 대해 알아보자.
단일 파일 매핑 오브젝트를 이용하여 두 개의 뷰를 매핑하는 예시 코드이다.
7. 메모리 맵 파일의 세부 구현사항
다른 형태의 세부 구현사항 대해 알아보자.
단일 파일 매핑 오브젝트를 이용하여 두 개의 뷰를 매핑하는 예시 코드이다.
8. 프로세스간 데이터 공유를 위해 메모리 맵 파일 사용하기
윈도우는 애플리케이션 간에 데이터와 정보를 빠르고 쉽게 공유할 수 있는 탁월한 메커니즘들을 제
공해 왔다. 이러한 메커니즘으로는 RPC, COM, DDE, 윈도우 메시지(특히 WM_COPYDATA), 클립
보드 메일슬롯, 파이프, 소켓 등이 있다.
단일의 윈도우 머신 내에서 데이터를 공유하는 가장 저수준의 메커니즘은 메모리 맵 파일이다.
실제로 앞서 언급한 다양한 공유 메커니즘들이 단일의 머신에서 수행되는 경우 결국에는 메모리 맹
파일을 이용하여 작업을 수행하게 된다. 만일 낮은 비용과 고성능으로 동작하는 공유 메커니즘이
필요하다면 메모리 맵 파일을 이용하는 것이 가장 좋은 방법이다.
둘 이상의 프로세스 사이에 데이터를 공유하려면 동일 파일 매핑 오브젝트에 대해 각 프로세스별로
뷰를 매핑하면 된다.
이렇게 하면 각 프로세스들은 통일한 물리적 저장소를 공유하게 된다. 결국 특정 프로세스에서
이처럼 공유되는 파일 매핑 오브젝트의 뷰 내의 데이터를 변경하게 되면 다른 프로세스는 자신의
뷰를 통해 이러한 변경사항이 즉각적으로 반영되는 것을 확인할 수 있다.
여러 개의 프로세스가 단일의 파일 매핑 오브젝트를 공유하려는 경우 동일한 파일 매핑 오브젝트
이름을 사용해야 한다.
9. 페이징 파일을 이용하는 메모리 맵 파일
많은 애플리케이션들이 수행 중에 데이터를 생성하고 이러한 데이터들을 다른 프로세스에
전달하거나 공유해야 할 필요가 있다.
이를 위해 애플리케이션이 디스크 드라이브 상에 데이터 파일을 생성하고, 그 안에 데이터를
저장하도록 하여 이를 공유하는 것은 매우 불편하다.
마이크로소프트는 이러한 불편함을 해소하기 위해 하드 디스크 상에 특정 파일을 사용하는 대신
시스템의 페이징 파일을 이용하여 메모리 맵 파일을 생성하는 방법을 제공하고 있다.
이러한 방법은 기존의 방법보다 더욱 쉽게 동일 작업을 수행할 수 있다는 점을 제외하고는 디스크
상에 사용자가 지정한 파일을 이용하는 방법과 매우 유사하다
메모리에 매핑할 파일을 열거나 생성할 필요가 없기 때문에 CreateFile 함수를 호출할 필요도 없다.
대신 CreateFileMapping 함수를 호출할 때 hFile 매개변수로 INVALID_HANDLE_VALUE를 전달해
주어 사용자가 디스크 상에 존재하는 파일을 물리적 저장소로 사용하는 파일 매핑 오브젝트를
생성하기를 원하지 않으며 시스템의 페이징 파일을 물리적 저장소로 사용하고 싶어 한다는 사실을
시스템에게 알려주면 된다.
시스템 페이징 파일 내에 할당되는 저장소의 크기는 CreateFileMapping 함수의
dwMaximumSizeHigh와 dwMaximumSizeLow매개변수에 의해 결정된다.
9. 페이징 파일을 이용하는 메모리 맵 파일
파일 매핑 오브젝트가 생성되고 프로세스의 주소 공간에 이에 대한 뷰가 매핑되고 나면 메모리 영역
을 통해 이 공간에 접근할 수 있게 된다.
만일 다른 프로세스와 데이터를 공유하려 한다면 CreateFileMapping 함수를 호출할 때 pszName
매개변수로 커널 오브젝트의 이름을 나타내는 문자열을 전달하면 된다. 공유된 데이터에
접근하고자 하는 프로세스는 CreateFileMapping이나 OpenFileMapping 함수를 호출할 때 동일한
커널 오브젝트 이름을 사용하면 된다.
만일 파일 매핑 오브젝트를 더 이상 사용할 필요가 없게 되면 CloseHandle 함수를 호출해야 한다.
해당 오브젝트를 참조하는 모든 핸들이 닫히게 되면 시스템은 페이징 파일 내의 커밋된 저장소를 해
제하게 된다.
10. 스파스 메모리 맵 파일
555쪽 “언제 물리적 저장소를 디커밋 하는가” 에서 논의했던 표계산 프로그램
• 만일 CELLDATA 구조체의 크기가 128 바이트라면 이 배열은 6.553.600(200 X256 X128)바이트의
물리적 저장소를 필요로 한다.
• CreateFileMapping 함수의 fdwProtect 매개변수 로 SEC_RESERVE 나 SEC_COMMIT 플래그를 지정하면
물리적 저장소의 예약과 커밋을 분리하여 수행할 수 있다.
• CreateFileMapping 함수를 호출할 때 SEC_COMMIT 플래그를 사용하면 시스템의 페이징 파일 내에 저장소를
커밋해 준다.
• CreateFileMapping 함수를 호출할 때 SEC_RESERVE 플래그를 사용하면 시스템은 시스템 페이징 파일로부터
물리적 저장소를 커밋하지 않은 상태로 파일 매핑 오브젝트의 핸들을 반환한다.
10. 스파스 메모리 맵 파일
공유된 영역에 대한 물리적 저장소를 커밋하려면 VirtualAlloc 함수를 호출하면된다.
VirtualAlloc 함수를 호출하여 메모리 맵 뷰 영역에 물리적 저장소를 커밋하는 것은 MEM_RESERVE 플래그를
이용하여 VirtualAlloc 함수를 호출하여 특정 영역을 예약한 후, 또 다시 VirtualAlloc 함수를 호출하여 물리적
저장소를 커밋하는 과정과 매우 흡사하다.
VirtuaAlloc 함수를 이용하여 예약된 영역에 대해 일부분만을 커밋할 수 있는 것과 같이 MapViewOfFile 이나
MapViewOfFileEx 함수를 호출하여 예약된 영역에 대해 VirtuaAlloc 함수를 호출하여 일부분만을 물리적
저장소로 커밋할 수 있다.
감사합니다

More Related Content

Similar to Windosw via c 스터디17장

Java rmi 개발 가이드
Java rmi 개발 가이드Java rmi 개발 가이드
Java rmi 개발 가이드중선 곽
 
Scalable web architecture and distributed systems
Scalable web architecture and distributed systemsScalable web architecture and distributed systems
Scalable web architecture and distributed systemseva
 
Scalable web architecture and distributed systems
Scalable web architecture and distributed systemsScalable web architecture and distributed systems
Scalable web architecture and distributed systems현종 김
 
LucideWorks Banana 소개
LucideWorks Banana 소개 LucideWorks Banana 소개
LucideWorks Banana 소개 SuHyun Jeon
 
ER/Studio 데이터 모델링 솔루션으로 마이그레이션(from ERwin)
ER/Studio 데이터 모델링 솔루션으로 마이그레이션(from ERwin)ER/Studio 데이터 모델링 솔루션으로 마이그레이션(from ERwin)
ER/Studio 데이터 모델링 솔루션으로 마이그레이션(from ERwin)Devgear
 
Hadoop Overview 1
Hadoop Overview 1Hadoop Overview 1
Hadoop Overview 1Kay Kim
 
Facebook이 대규모 확장성 도전에서 배운 것
Facebook이 대규모 확장성 도전에서 배운 것Facebook이 대규모 확장성 도전에서 배운 것
Facebook이 대규모 확장성 도전에서 배운 것흥배 최
 
PINTOS Operating system homework
PINTOS Operating system homeworkPINTOS Operating system homework
PINTOS Operating system homeworkGichan Lee
 
실용주의 프로그래머를 위한 개발환경 만들기
실용주의 프로그래머를 위한 개발환경 만들기실용주의 프로그래머를 위한 개발환경 만들기
실용주의 프로그래머를 위한 개발환경 만들기Mickey SJ Lee
 
[HaU] 신입 기술 면접 준비 java
[HaU] 신입 기술 면접 준비 java[HaU] 신입 기술 면접 준비 java
[HaU] 신입 기술 면접 준비 java유리 하
 
프로그래밍 언어 기초(델파이,C++)
프로그래밍 언어 기초(델파이,C++)프로그래밍 언어 기초(델파이,C++)
프로그래밍 언어 기초(델파이,C++)Devgear
 
멀티티어 애플리케이션 개발과 배포
멀티티어 애플리케이션 개발과 배포멀티티어 애플리케이션 개발과 배포
멀티티어 애플리케이션 개발과 배포Devgear
 
Tdc2013 선배들에게 배우는 server scalability
Tdc2013 선배들에게 배우는 server scalabilityTdc2013 선배들에게 배우는 server scalability
Tdc2013 선배들에게 배우는 server scalability흥배 최
 
Rankwave MOMENT™ (Korean)
Rankwave MOMENT™ (Korean)Rankwave MOMENT™ (Korean)
Rankwave MOMENT™ (Korean)HyoungEun Kim
 
[스프링 스터디 1일차] 템플릿
[스프링 스터디 1일차] 템플릿[스프링 스터디 1일차] 템플릿
[스프링 스터디 1일차] 템플릿AnselmKim
 

Similar to Windosw via c 스터디17장 (20)

Java rmi 개발 가이드
Java rmi 개발 가이드Java rmi 개발 가이드
Java rmi 개발 가이드
 
Scalable web architecture and distributed systems
Scalable web architecture and distributed systemsScalable web architecture and distributed systems
Scalable web architecture and distributed systems
 
Scalable web architecture and distributed systems
Scalable web architecture and distributed systemsScalable web architecture and distributed systems
Scalable web architecture and distributed systems
 
Oracle History #7
Oracle History #7Oracle History #7
Oracle History #7
 
7. html5 api
7. html5 api7. html5 api
7. html5 api
 
Final report201101
Final report201101Final report201101
Final report201101
 
LucideWorks Banana 소개
LucideWorks Banana 소개 LucideWorks Banana 소개
LucideWorks Banana 소개
 
ER/Studio 데이터 모델링 솔루션으로 마이그레이션(from ERwin)
ER/Studio 데이터 모델링 솔루션으로 마이그레이션(from ERwin)ER/Studio 데이터 모델링 솔루션으로 마이그레이션(from ERwin)
ER/Studio 데이터 모델링 솔루션으로 마이그레이션(from ERwin)
 
Git - Level 2
Git - Level 2Git - Level 2
Git - Level 2
 
Hadoop Overview 1
Hadoop Overview 1Hadoop Overview 1
Hadoop Overview 1
 
Gfs Kyu
Gfs KyuGfs Kyu
Gfs Kyu
 
Facebook이 대규모 확장성 도전에서 배운 것
Facebook이 대규모 확장성 도전에서 배운 것Facebook이 대규모 확장성 도전에서 배운 것
Facebook이 대규모 확장성 도전에서 배운 것
 
PINTOS Operating system homework
PINTOS Operating system homeworkPINTOS Operating system homework
PINTOS Operating system homework
 
실용주의 프로그래머를 위한 개발환경 만들기
실용주의 프로그래머를 위한 개발환경 만들기실용주의 프로그래머를 위한 개발환경 만들기
실용주의 프로그래머를 위한 개발환경 만들기
 
[HaU] 신입 기술 면접 준비 java
[HaU] 신입 기술 면접 준비 java[HaU] 신입 기술 면접 준비 java
[HaU] 신입 기술 면접 준비 java
 
프로그래밍 언어 기초(델파이,C++)
프로그래밍 언어 기초(델파이,C++)프로그래밍 언어 기초(델파이,C++)
프로그래밍 언어 기초(델파이,C++)
 
멀티티어 애플리케이션 개발과 배포
멀티티어 애플리케이션 개발과 배포멀티티어 애플리케이션 개발과 배포
멀티티어 애플리케이션 개발과 배포
 
Tdc2013 선배들에게 배우는 server scalability
Tdc2013 선배들에게 배우는 server scalabilityTdc2013 선배들에게 배우는 server scalability
Tdc2013 선배들에게 배우는 server scalability
 
Rankwave MOMENT™ (Korean)
Rankwave MOMENT™ (Korean)Rankwave MOMENT™ (Korean)
Rankwave MOMENT™ (Korean)
 
[스프링 스터디 1일차] 템플릿
[스프링 스터디 1일차] 템플릿[스프링 스터디 1일차] 템플릿
[스프링 스터디 1일차] 템플릿
 

More from HolyTak

14장 입자 시스템과 스트림 출력.pptx
14장 입자 시스템과 스트림 출력.pptx14장 입자 시스템과 스트림 출력.pptx
14장 입자 시스템과 스트림 출력.pptxHolyTak
 
Graphics 14장 1인칭 카메라 만들기.pptx
Graphics 14장 1인칭 카메라 만들기.pptxGraphics 14장 1인칭 카메라 만들기.pptx
Graphics 14장 1인칭 카메라 만들기.pptxHolyTak
 
Graphics 8장 텍스처 적용.pptx
Graphics 8장 텍스처 적용.pptxGraphics 8장 텍스처 적용.pptx
Graphics 8장 텍스처 적용.pptxHolyTak
 
Graphics 2장 행렬.pptx
Graphics 2장 행렬.pptxGraphics 2장 행렬.pptx
Graphics 2장 행렬.pptxHolyTak
 
Windosw via c 스터디26장.pptx
Windosw via c 스터디26장.pptxWindosw via c 스터디26장.pptx
Windosw via c 스터디26장.pptxHolyTak
 
Windosw via c 스터디23장.pptx
Windosw via c 스터디23장.pptxWindosw via c 스터디23장.pptx
Windosw via c 스터디23장.pptxHolyTak
 
Windosw via c 스터디23장.pptx
Windosw via c 스터디23장.pptxWindosw via c 스터디23장.pptx
Windosw via c 스터디23장.pptxHolyTak
 
Windosw via c 스터디12장
Windosw via c 스터디12장Windosw via c 스터디12장
Windosw via c 스터디12장HolyTak
 
Windows via c/c++ 스터디9장
Windows via c/c++ 스터디9장Windows via c/c++ 스터디9장
Windows via c/c++ 스터디9장HolyTak
 
Windosw via c/c++ 스터디5장
Windosw via c/c++ 스터디5장Windosw via c/c++ 스터디5장
Windosw via c/c++ 스터디5장HolyTak
 
Windosw via c 스터디2장
Windosw via c 스터디2장Windosw via c 스터디2장
Windosw via c 스터디2장HolyTak
 

More from HolyTak (11)

14장 입자 시스템과 스트림 출력.pptx
14장 입자 시스템과 스트림 출력.pptx14장 입자 시스템과 스트림 출력.pptx
14장 입자 시스템과 스트림 출력.pptx
 
Graphics 14장 1인칭 카메라 만들기.pptx
Graphics 14장 1인칭 카메라 만들기.pptxGraphics 14장 1인칭 카메라 만들기.pptx
Graphics 14장 1인칭 카메라 만들기.pptx
 
Graphics 8장 텍스처 적용.pptx
Graphics 8장 텍스처 적용.pptxGraphics 8장 텍스처 적용.pptx
Graphics 8장 텍스처 적용.pptx
 
Graphics 2장 행렬.pptx
Graphics 2장 행렬.pptxGraphics 2장 행렬.pptx
Graphics 2장 행렬.pptx
 
Windosw via c 스터디26장.pptx
Windosw via c 스터디26장.pptxWindosw via c 스터디26장.pptx
Windosw via c 스터디26장.pptx
 
Windosw via c 스터디23장.pptx
Windosw via c 스터디23장.pptxWindosw via c 스터디23장.pptx
Windosw via c 스터디23장.pptx
 
Windosw via c 스터디23장.pptx
Windosw via c 스터디23장.pptxWindosw via c 스터디23장.pptx
Windosw via c 스터디23장.pptx
 
Windosw via c 스터디12장
Windosw via c 스터디12장Windosw via c 스터디12장
Windosw via c 스터디12장
 
Windows via c/c++ 스터디9장
Windows via c/c++ 스터디9장Windows via c/c++ 스터디9장
Windows via c/c++ 스터디9장
 
Windosw via c/c++ 스터디5장
Windosw via c/c++ 스터디5장Windosw via c/c++ 스터디5장
Windosw via c/c++ 스터디5장
 
Windosw via c 스터디2장
Windosw via c 스터디2장Windosw via c 스터디2장
Windosw via c 스터디2장
 

Recently uploaded

공학 관점에서 바라본 JMP 머신러닝 최적화
공학 관점에서 바라본 JMP 머신러닝 최적화공학 관점에서 바라본 JMP 머신러닝 최적화
공학 관점에서 바라본 JMP 머신러닝 최적화JMP Korea
 
JMP가 걸어온 여정, 새로운 도약 JMP 18!
JMP가 걸어온 여정, 새로운 도약 JMP 18!JMP가 걸어온 여정, 새로운 도약 JMP 18!
JMP가 걸어온 여정, 새로운 도약 JMP 18!JMP Korea
 
JMP 기능의 확장 및 내재화의 핵심 JMP-Python 소개
JMP 기능의 확장 및 내재화의 핵심 JMP-Python 소개JMP 기능의 확장 및 내재화의 핵심 JMP-Python 소개
JMP 기능의 확장 및 내재화의 핵심 JMP-Python 소개JMP Korea
 
JMP를 활용한 전자/반도체 산업 Yield Enhancement Methodology
JMP를 활용한 전자/반도체 산업 Yield Enhancement MethodologyJMP를 활용한 전자/반도체 산업 Yield Enhancement Methodology
JMP를 활용한 전자/반도체 산업 Yield Enhancement MethodologyJMP Korea
 
JMP를 활용한 가속열화 분석 사례
JMP를 활용한 가속열화 분석 사례JMP를 활용한 가속열화 분석 사례
JMP를 활용한 가속열화 분석 사례JMP Korea
 
실험 설계의 평가 방법: Custom Design을 중심으로 반응인자 최적화 및 Criteria 해석
실험 설계의 평가 방법: Custom Design을 중심으로 반응인자 최적화 및 Criteria 해석실험 설계의 평가 방법: Custom Design을 중심으로 반응인자 최적화 및 Criteria 해석
실험 설계의 평가 방법: Custom Design을 중심으로 반응인자 최적화 및 Criteria 해석JMP Korea
 
데이터 분석 문제 해결을 위한 나의 JMP 활용법
데이터 분석 문제 해결을 위한 나의 JMP 활용법데이터 분석 문제 해결을 위한 나의 JMP 활용법
데이터 분석 문제 해결을 위한 나의 JMP 활용법JMP Korea
 

Recently uploaded (7)

공학 관점에서 바라본 JMP 머신러닝 최적화
공학 관점에서 바라본 JMP 머신러닝 최적화공학 관점에서 바라본 JMP 머신러닝 최적화
공학 관점에서 바라본 JMP 머신러닝 최적화
 
JMP가 걸어온 여정, 새로운 도약 JMP 18!
JMP가 걸어온 여정, 새로운 도약 JMP 18!JMP가 걸어온 여정, 새로운 도약 JMP 18!
JMP가 걸어온 여정, 새로운 도약 JMP 18!
 
JMP 기능의 확장 및 내재화의 핵심 JMP-Python 소개
JMP 기능의 확장 및 내재화의 핵심 JMP-Python 소개JMP 기능의 확장 및 내재화의 핵심 JMP-Python 소개
JMP 기능의 확장 및 내재화의 핵심 JMP-Python 소개
 
JMP를 활용한 전자/반도체 산업 Yield Enhancement Methodology
JMP를 활용한 전자/반도체 산업 Yield Enhancement MethodologyJMP를 활용한 전자/반도체 산업 Yield Enhancement Methodology
JMP를 활용한 전자/반도체 산업 Yield Enhancement Methodology
 
JMP를 활용한 가속열화 분석 사례
JMP를 활용한 가속열화 분석 사례JMP를 활용한 가속열화 분석 사례
JMP를 활용한 가속열화 분석 사례
 
실험 설계의 평가 방법: Custom Design을 중심으로 반응인자 최적화 및 Criteria 해석
실험 설계의 평가 방법: Custom Design을 중심으로 반응인자 최적화 및 Criteria 해석실험 설계의 평가 방법: Custom Design을 중심으로 반응인자 최적화 및 Criteria 해석
실험 설계의 평가 방법: Custom Design을 중심으로 반응인자 최적화 및 Criteria 해석
 
데이터 분석 문제 해결을 위한 나의 JMP 활용법
데이터 분석 문제 해결을 위한 나의 JMP 활용법데이터 분석 문제 해결을 위한 나의 JMP 활용법
데이터 분석 문제 해결을 위한 나의 JMP 활용법
 

Windosw via c 스터디17장

  • 2. • 메모리 맵 파일 기능은 가상 메모리처럼 주소공간을 예약하고 예약된 영역에 물리적 저장소를 커밋하는 제공한다. • 시스템 페이징 파일을 사용하는 대신 디스크 상에 존재하는 파일을 물리적 저장소로 사용한다. • 이러한 파일이 일단 영역에 매핑되면 마치 메모리에 파일의 내용이 모드 로드된 것처럼 사용할 수 있다. • 시스템은 exe나 DLL 파일을 읽고 수행하기 위해 메모리 맵 파일을 사용한다. 이로인해 시스템은 페이징 파일의 크기를 일정하게 유지할 수 있으며, 애플리케이션의 시작시간도 일정하게 유지할 수 있다. • 디스크에 있는 데이터에 접근하기 위해 메모리 맵 파일을 사용할 수 있다. 메모리 맵 파일을 사용하면 파일에 대한 I/O작업이나 파일의 내용에 대한 버퍼링을 자동적으로 수행해 준다. • 동일한 머신에서 수행중인 다수의 프로세스 간에 데이터를 공유하기 위해서 메모리 맵 파일을 사용할 수도 있다. 윈도우는 프로세스들 사이에 데이터를 전달하는 다양한 방법들을 제공하고 있지만 내부적으로는 모두 메모리 맵 파일을 사용하여 구현되어있으며, 실제로 메모리 맵 파일을 사용하는 것이 단일의 머신에서 프로세스 간에 데이터를 전달하는 가장 효과적인 방법이다.
  • 3. 1. 실행 파일과 DLL 파일에 대한 메모리 맵 CreateProcess를 호출하면 시스템은 다음과 같은 절차를 순차적으로 수행한다. 1. 시스템은 CreateProcess 함수의 매개변수로 전달된 exe파일을 찾는다. 만약 존재하지 않으면 프로세스는 생성되지 않으며, CreateProcess 함수는 false를 반환하게 된다. 2. 시스템은 새로운 프로세스 커널 오브젝트를 생성한다. 3. 시스템은 새로운 프로세스를 위한 전용의 주소 공간을 생성한다. 4. 시스템은 exe파일을 수용할 수 있을 만큼의 충분한 영역을 주소 공간 내에 예약한다. Exe파일이 선호하는 시작 주소는 일반덕으로 exe파일 내에 기록되어 있으며, 시작 주소는 0x00400000이다.(기본 시작 주소는 64비트 윈도우에서 64비트 애플리케이션을 수행할 때에는 달라질 수 있다.) 이 값은 애플리케이션을 링크할 때 /BASE 링커 옵션을 이용하여 변경이 가능하다. 5. 시스템은 예약된 영역에 사용할 물리적 저장소로 시스템의 페이징 파일 대신 exe파일 자체를 지정한다.
  • 4. 1. 실행 파일과 DLL 파일에 대한 메모리 맵 정적 데이터는 실행 파일과 DLL의 여러 인스턴스들 사이에 공유되지 않는다. 이미 수행중인 애플리케이션을 다시 한번 수행하면, 시스템은 앞서 수행되었던 실행 파일 이미지를 가리키는 파일 매핑 오브젝트를 투영하는 새로운 메모리 맵 뷰에 대한 열기 작업을 수행하고, 새로운 프로세스 오브젝트와 새로운 스레드 오브젝트를 생성한 후, 각 오브젝트별로 새로운 프로세스 ID와 스레드ID를 부여한다. 메모리 맵 파일을 이용하면 동일 애플리케이션의 인스턴스가 여러 번 수행될 경우 램 상에 이미 로드된 코드와 데이터를 공유하게 된다. 하지만 이러한 동작 방식에는 문제를 유발할 소지가 있다. 프로세스들은 순차적으로 펼쳐진 메모리 주소공간을 이용하고 있다. 프로그램을 컴파일하고 링크하게 되면 코드와 데이터는 단일의 파일로 구성되게 된다. 물론 데이터와 코드가 서로 다른 영역으로 분리되어 있긴 하지만, 엄연히 말해 단일의 exe파일 내에 함께 내장되어 있는 것은 사실이다.
  • 5. 1. 실행 파일과 DLL 파일에 대한 메모리 맵 실제로 어떻게 가상메모리에 로드되고 애플리케이션의 주소공간에 매핑 되는지를 나타낸 것이다.
  • 6. 1. 실행 파일과 DLL 파일에 대한 메모리 맵 애플리케이션의 두 번째 인스턴스가 수행되면 시스템은 가상 메모리에 로드되어 있는 코드와 데이터를 두 번째 인스턴스의 주소 공간에 매핑한다.
  • 7. 1. 실행 파일과 DLL 파일에 대한 메모리 맵 아래 그림은 애플리케이션의 첫 번째 인스턴스가 데이터 페이지 2번에 저장되어 있는 전역변수의 내용을 변경하려고 시도하였을 때의 모습을 그림으로 나타낸 것이다.
  • 8. 1. 실행 파일과 DLL 파일에 대한 메모리 맵 실행 파일과 DLL의 여러 인스턴스들 사이에 정적 데이터 공유하기 exe나 DLL 파일 내에 전역으로 선언된 정적 데이터들은 파일들이 서로 다른 여러 프로세스들의 주 소공간에 각기 매핑되더라도 기본적으로 그 내용을 공유하지 않는다. 하지만 때로는 exe나 DLL 파 일이 서로 다른 프로세스들의 주소 공간 상에 여러 번 매핑된다 하더라도 변수의 내용을 공유할 수 있으면 유용할 때가 있다. 예를 면, 윈도우는 통일 애플리케이션이 이전에 수행된 적이 있는지를 간단하게 확인할 수 있는 방법이 없다. 만일 전역변수가 모든 인스턴스들 사이에서 공유될 수 있다면 이를 통해 동일 애플리케이션의 반복 수행 횟수를 저장해 두어 동일 애플리케이션이 이전에 이미 수행 중인지의 여부를 쉽게 확인할 수 있다. 즉 사용자가 애플리케이션의 새로운 인스턴스를 수행하였을 때 먼저 전역변수의 내용을 확인하고 이 값이 1 일 경우통일 애플리케이션이 이미 수행 중이며, 자신이 두 번째 인스턴스임을 알 수 있다. 이 경우 사용자에게 이 애플리케이션은 유일하게 한 번만 수행할 수 있음을 알려주고 종료할 수도 있다. 이렇듯 exe와 DLL의 모든 인스턴스들 사이에서 변수를 공유하는 기법은 앞으로 논의할 섹션 기법 을 이용함으로써 가능하다. 하지만 이에 대해 자세히 살펴보기 전에 조금의 배경 지식이 필요하다. 모든 exe와 DLL 파일 이미지는 섹션들의 집합으로 구성되어 있다. 편의를 위해 표준 섹션들은 점으 로 시작하는 이름을 가지고 있다. 예를 들어 프로그램을 컴파일하게 되면 컴파일러는 자신이 생성한 모든 코드를 .text라는 이름의 섹션 내에 배치한다. 또한 초기화되지 않은 데이터는 .bss 섹션에, 초 기화된 데이터는 .data 섹션에 각각 나누어 배치한다.
  • 9. 1. 실행 파일과 DLL 파일에 대한 메모리 맵 실행 파일과 DLL의 여러 인스턴스들 사이에 정적 데이터 공유하기
  • 10. 1. 실행 파일과 DLL 파일에 대한 메모리 맵 컴파일러나 링커가 생성해 주는 표준 섹션 이름 외에도 소스 코드에 다음과 같은 지시어를 사용하여 자신만의 섹션 이름을 지정할 수 있다 예를 들어 Shared라는 이름의 섹션을 만들고 그 안에 LONG 값을 저장하고 싶다면 다음과 같이 코드를 작성하면 된다. 컴파일러가 이 코드를 컴파일하게 되면 Shared라는 이름의 새로운 섹션을 생성하고 pragma 이후 에 나타낸 모든 초기화된 데이터 변수를 해당 섹션 안에 추가한다.
  • 11. 1. 실행 파일과 DLL 파일에 대한 메모리 맵 마이크로소프트 Visual C++ 컴파일러는 allocate라는 선언 지정자 declaration specifier를 제공하여 초기화되지 않은 데이터의 경우에도 사용자가 지정한 섹션에 내용을 추가할 수 있도록 해 주고 있다.
  • 12. 1. 실행 파일과 DLL 파일에 대한 메모리 맵 Allocate 선언 지정자가 정상적으로 동작하도록 하려면 항상 해당 섹션이 먼저 생성되어 있어야 한다. 따라서 위 코드에서 #pragma data_seg 행들을 제거해 버리면 코드는 정상적으로 컴파일 되지 않을 것이다. 새로운 섹션을 구성하고, 그 섹션에 변수들을 추가하는 대부분의 경우는 exe와 DLL 파일이 다수의 프로세스 공간에 여러 번 매핑 되더라도 해당 변수를 공유할 수 있도록 하기 위함일 것이다. 이렇게 새로운 섹션에 여러 개의 변수를 삽입해 두면 여러 개의 인스턴스 사이에 공유할 수 있는 일련의 데이터 그룹을 구성할 수 있게 된다. 이러한 데이터 그룹들은 exe 나 DLL 파일들이 새롭게 생성된 프로세스의 주소공간에 추가적으로 매핑되더라도 변수에 대한 새로운 인스턴스를 생성하지 않고 기존의 값을 공유하게 된다.
  • 13. 1. 실행 파일과 DLL 파일에 대한 메모리 맵 단순히 컴파일러에게 몇몇 변수들을 고유의 섹션 내에 배치하도록 하는 것만으로 변수를 공유할 수 있는 것은아니다. 추가적으로 링크단계에서 링커에게 특정 섹션은 공유되어야 한다는 사실을 반드시 알 려주어야만 하는데 링커스위치 중 / SECTION을 이용함으로써 이러한 작업을 수행할 수 있다. 콜론 기호 이후에는 섹션의 이름과 해당 섹션에 적용할 특성 정보를 지정하면 된다. Shared 섹션의 특성을 변경해야 하므로 다음과 같이 링커 스위치를 사용하면 된다.
  • 14. 1. 실행 파일과 DLL 파일에 대한 메모리 맵 쉽표 기호 이후에는 필요한 특성 정보를 나열하면 되는데 R은 읽기, W는 쓰기, E는 실행, S는 공유를 의미한다. 위 스위치의 경우 Shared 섹션 내의 데이터는 읽고 쓰는 것이 가능한 공유 섹션임을 지정하게 된다. 만일 한 개 이상의 섹션에 대해 특성 정보를 변경하고 싶은 경우라면 /SECTION 스위치를 여러 번 사용하면 된다. 이러한 방법 외에도 소스코드 내에 다음과 같이 링커 스위치를 포함시킬 수도 있다. 위와 같은 행을 포함시키면 컴파일러는 obj 파일 내에 “ .drectve'’ 라는 이름의 특수한 섹션을 생성하 여 그 안에 지정된 문자열을 포함시키게 된다. 링커는 .obj 모률을 결합할 때 .obj 모듈 내의 “ drectve" 섹션 내의 문자열을 확인하고, 해당 문자열이 마치 링커의 명령행 인자로 전달된 것처럼 링크를 수행하게 된다.
  • 15. 1. 실행 파일과 DLL 파일에 대한 메모리 맵 이와 같이 사용자가 임의로 공유 섹션을 만들 수 있음에도 불구하고, 마이크로소프트는 두 가지 이유로 인해 공유 섹션을 사용하지 말 것을 권고한다. • 공유되는 메모리를 사용하게 되면 잠재적으로 보안에 취약해질 가능성이 있다. • 공유변수를 사용하게 되면 특정 애플리케이션 내에서 발생하는 에러가 다른 애플리케이션에 직접적인 영향을 줄 수 있다. • 실제로 애플리케이션 내에서 공유변수에 대해 임의로 접근하는 것을 막을 수 있는 방법이 존재하지 않는다.
  • 16. 2. 메모리 맵 데이터 파일 운영체제는 프로세스의 주소공간에 데이터 파일을 매핑할 수 있기 때문에 크기가 큰 데이터 스트림을 편리하게 다룰 수 있다. 방법 1: 한개의 파일, 한개의 버퍼 첫 번째 방법은 이론적으로 가장 간단한 방법으로 파일 전체의 내용을 모두 읽을 수 있는 충분한 크 기의 메모리 블록을 할당하는 방법이다. 파일을 열고 메모리로 그 내용을 모두 읽어온 뒤 파일을 닫는다. 이후 메모리에 파일의 내용이 모두 담겨 있으므로 첫 번째 바이트와 마지막 바이트를 교환하 고 , 두 번째 바이트와 마지막에서 두 번째 바이트를 교환하는 식으로 반복한다. 파일의 중간에 도달할 때까지 이러한 교환 작업을 반복한 이후 파일을 다시 열고 메모리 블록의 내용을 파 일로 덮어쓴다.
  • 17. 2. 메모리 맵 데이터 파일 방법 2: 두 개의 파일, 한 개의 버퍼 두 번째 방법은 기존 파일을 여는 것과 동시에 파일 크기가 0 인 파일을 새로 생성하는 방법이다. 내부적으로 8KB 정도의 작은 버퍼를 할당하고 기존 파일의 가장 끝으로부터 8KB만큼 떨어진 곳으로 이동한 후 파일의 마지막 8KB를 버퍼로 읽어 들인다. 이제 버퍼의 내용을 뒤집고, 새롭게 생성한 파일에 그 내용을 저장한다. 처리 과정은 파일 포인터 이동, 읽기, 뒤집기, 쓰기 순으로 반복되며, 이러한 과정을 기존 파일의 시작에 다다를 때까지 반복한다. 어려운 작업이 아니긴 하지만 기존 파일의 크기가 8KB의 배수가 아닌 경우 특별한 처리가 필요하다. 기존 파일에 대한 처리가 모두 완료되면, 두 파일을 닫고 기존 파일을 삭제한다.
  • 18. 2. 메모리 맵 데이터 파일 방법 3: 한 개의 파일, 두 개의 버퍼 방법은 두 개의 8KB 크기의 버퍼를 할당하는 것으로 시작한다. 프로그램은 파일로부터 가장 앞쪽의 8KB와 가장 뒤쪽의 8KB를 각각 서로 다른 버퍼로 읽어 들인다. 이후 각 버퍼의 내용을 뒤집고 파일의 앞쪽 내용을 담아두었던 버퍼의 내용을 파일의 뒤쪽에, 파일의 뒤쪽 내용을 담아두었던 버퍼의 내용을 파일의 앞쪽에 덮어쓴다. 이러한 작업을 파일 전체 내용에 대해 반복한다. 이 방법은 파일의 크기가 16KB 의 배수가 아니어서 8KB 의 버퍼로 읽어올 경우 내용이 겹치는 경우에 특별한 처리가 필요하다. 이러한 고려사항을 처리하기 위해서는 두 번째 방법의 경우에 비해 상당히 복잡한 코드를 필요로 한다.
  • 19. 2. 메모리 맵 데이터 파일 방법 4: 한 개의 파일, 버퍼는 사용하지 않음 메모리 맵 파일을 이용하여 파일의 내용을 뒤집기 위해서는 파일을 열고 가상 주소 공간 상에 영역을 예약한 뒤 파일의 첫 번째 바이트와 예약된 영역의 첫 번째 위치를 매핑시킨다. 이후 가상 메모리 주소에 접근하게 되면 이는 마치 파일의 내용에 직접적으로 접근하는 것과 같은 효과를 가져온다. 텍스트 파일의 내용이 0으로 끝나는 경우 파일의 내용이 모두 메모리에 있는 것과 같이 C 런타임 라이브러리에서 제공하는 _tcsrev 함수를 호출하여 파일의 내용을 모두 뒤집을 수 있다.
  • 20. 3. 메모리 맵 파일 사용하기. 메모리 맵 파일을 사용하려면 다음의 세가지 단계를 수행해야 한다. 1. 메모리 맵 파일로 사용할 디스크 상의 파일을 나타내는 파일 커널 오브젝트를 생성하거나 연다. 2. 파일의 크기와 파일의 접근 방식을 고려하여 파일 매핑 커널 오브젝트를 생성한다. 3. 프로세스의 주소 공간 상에 파일 매 핑 오브젝트의 전체나 일부를 매핑시킨다. 메모리 맵 파일을 더 이상 허용할 필요가 없다면 다음의 세 가지 단계를 수행해야 한다. 1. 프로세스의 주소 공간으로부터 파일 매핑 오브젝트의 매핑을 해제한다. 2. 파일 매핑 커널 오브젝트를 닫는다. 3. 파일 커널 오브젝트를 닫는다. 614p 참고
  • 21. 4. 메모리 맵 파일을 이용하여 큰 파일 처리하기 8GB 크기의 파일을 32 비트 주소 공간을 통해 접근하는. 아래에 몇 가지 단계를 통해 파일 내에 존재하는 0의 개수를 세어보는 루틴.
  • 22. 5. 메모리 맵 파일과 일관성 사용자는 특정 파일 내의 동일 데이터에 대해 여러 개의 뷰를 생성하여 프로세스의 주소 공간에 매핑 할 수 있다. 예를 들어 파일의 앞쪽으로부터 10KB의 내용을 특정 뷰에 매핑한 후, 또 다른 뷰에 파일 의 앞쪽으로부터 4KB 의 내용을 매핑할 수 있다. 단일의 파일 매핑 오브젝트를 여러 개의 뷰를 이용 하여 매핑하는 경우에는 파일 내의 데이터에 대한 일관성이 유지된다. 즉 애플리케이션이 특정 뷰를 통해 그 내용을 변경하게 되면 다른 뷰에도 변경사항이 모두 반영된다. 다른 프로세스가 이미 매핑하고 있는 파일이라 하더라도 새로운 프로세스는 추가적으로 CreateFile 함수를 호출하여 열기 작업을 수행할 수 있으며 ReadFile과 WriteFile 함수를 이용하여 파일에 대한 읽기와 쓰기 작업을 수행할 수 있다. 물론 프로세스가 이러한 함수들을 호출하는 이유는 파일로부터 메모리 버퍼로 데이터를 가져오거나 메모리 버퍼에 존재하는 데이터를 파일로 쓰기 위함이다. 이러한 메모리 버퍼는 새로 생성한 프로세스가 생성한 것이며 파일 매핑을 위해 사용되는 메모리는 아닐 것이다. 그런데 이처럼 두 개의 프로세스가 동시에 동일한 파일에 대해 열기 작업을 수행한 경 우 문제가 발생할 소지가 있다. 파일 매핑 오브젝트를 이용하여 파일을 사용하는 프로세스가 있는 경우에도 별도의 프로세스가 ReadFile을 이용하여 동일한 파일의 데이터를 읽고, 그 내용을 수정하고, WriteFile을 이용하여 파일의 내용을 수정할 수 있다. 이러한 이유로 파일을 메모리에 매핑하여 사용하길 원한다면 CreateFile을 호출할 때 dwShareMode 매개변수로 0을 지정할 것을 권고한다. 이렇게 함으로써 시용자가 파일에 대한 배타적인 접근 권한을 요구한다는 사실을 시스템에 알려줄 수 있으며, 이 경우 다른 프로세스는 해당 파일을 추가적으로 열지 못하기 때문에 일관성 문제를 유발하지 않는다.
  • 23. 6. 메모리 맵 파일의 시작 주소 지정하기 VirtualAlloc 함수를 사용할 때 예약할 주소 공간의 시작 주소를 전달할 수 있는 것과 같이 MapViewOfFile함수 대신 MapViewOfFileEx 함수를 사용하면 매핑할 시작 주소를 지정할 수 있다.
  • 24. 7. 메모리 맵 파일의 세부 구현사항 프로세스의 주소 공간을 통해 파일 데이터에 접근하려면 MapViewOfFile 함수를 먼저 호출해 주어 야 한다. 프로세스가 MapViewOfFile 함수를 호출하면 시스템은 해당 함수를 호출한 프로세스의 주소 공간 내에 뷰를 매핑할 영역을 예약한다. 따라서 다른 프로세스는 이러한 뷰를 볼 수 없다. 만일 다른 프로세스가 동일 파일 매핑 오브젝트를 이용하여 파일 데이터에 접근하고자 한다면 MapViewOfFile함수를 재호출하여 자신의 프로세스 주소 공간 내에 영역을 확보해야만 한다. 특정 프로세스에서 Map ViewOfFile 함수를 호출하였을 때 반환되는 메모리 주소는 다른 프로세스 에서 Map ViewOfFile 함수를 호출하였을 때 반환되는 주소외는 다르다는 점에 특히 주의할 필요가 있다. 이러한 특성은 여러 개의 프로세스가 동일 파일 오브젝트를 이용하여 뷰를 매핑한다 하더라도 동일하게적용된다.
  • 25. 7. 메모리 맵 파일의 세부 구현사항 다른 형태의 세부 구현사항 대해 알아보자. 단일 파일 매핑 오브젝트를 이용하여 두 개의 뷰를 매핑하는 예시 코드이다.
  • 26. 7. 메모리 맵 파일의 세부 구현사항 다른 형태의 세부 구현사항 대해 알아보자. 단일 파일 매핑 오브젝트를 이용하여 두 개의 뷰를 매핑하는 예시 코드이다.
  • 27. 8. 프로세스간 데이터 공유를 위해 메모리 맵 파일 사용하기 윈도우는 애플리케이션 간에 데이터와 정보를 빠르고 쉽게 공유할 수 있는 탁월한 메커니즘들을 제 공해 왔다. 이러한 메커니즘으로는 RPC, COM, DDE, 윈도우 메시지(특히 WM_COPYDATA), 클립 보드 메일슬롯, 파이프, 소켓 등이 있다. 단일의 윈도우 머신 내에서 데이터를 공유하는 가장 저수준의 메커니즘은 메모리 맵 파일이다. 실제로 앞서 언급한 다양한 공유 메커니즘들이 단일의 머신에서 수행되는 경우 결국에는 메모리 맹 파일을 이용하여 작업을 수행하게 된다. 만일 낮은 비용과 고성능으로 동작하는 공유 메커니즘이 필요하다면 메모리 맵 파일을 이용하는 것이 가장 좋은 방법이다. 둘 이상의 프로세스 사이에 데이터를 공유하려면 동일 파일 매핑 오브젝트에 대해 각 프로세스별로 뷰를 매핑하면 된다. 이렇게 하면 각 프로세스들은 통일한 물리적 저장소를 공유하게 된다. 결국 특정 프로세스에서 이처럼 공유되는 파일 매핑 오브젝트의 뷰 내의 데이터를 변경하게 되면 다른 프로세스는 자신의 뷰를 통해 이러한 변경사항이 즉각적으로 반영되는 것을 확인할 수 있다. 여러 개의 프로세스가 단일의 파일 매핑 오브젝트를 공유하려는 경우 동일한 파일 매핑 오브젝트 이름을 사용해야 한다.
  • 28. 9. 페이징 파일을 이용하는 메모리 맵 파일 많은 애플리케이션들이 수행 중에 데이터를 생성하고 이러한 데이터들을 다른 프로세스에 전달하거나 공유해야 할 필요가 있다. 이를 위해 애플리케이션이 디스크 드라이브 상에 데이터 파일을 생성하고, 그 안에 데이터를 저장하도록 하여 이를 공유하는 것은 매우 불편하다. 마이크로소프트는 이러한 불편함을 해소하기 위해 하드 디스크 상에 특정 파일을 사용하는 대신 시스템의 페이징 파일을 이용하여 메모리 맵 파일을 생성하는 방법을 제공하고 있다. 이러한 방법은 기존의 방법보다 더욱 쉽게 동일 작업을 수행할 수 있다는 점을 제외하고는 디스크 상에 사용자가 지정한 파일을 이용하는 방법과 매우 유사하다 메모리에 매핑할 파일을 열거나 생성할 필요가 없기 때문에 CreateFile 함수를 호출할 필요도 없다. 대신 CreateFileMapping 함수를 호출할 때 hFile 매개변수로 INVALID_HANDLE_VALUE를 전달해 주어 사용자가 디스크 상에 존재하는 파일을 물리적 저장소로 사용하는 파일 매핑 오브젝트를 생성하기를 원하지 않으며 시스템의 페이징 파일을 물리적 저장소로 사용하고 싶어 한다는 사실을 시스템에게 알려주면 된다. 시스템 페이징 파일 내에 할당되는 저장소의 크기는 CreateFileMapping 함수의 dwMaximumSizeHigh와 dwMaximumSizeLow매개변수에 의해 결정된다.
  • 29. 9. 페이징 파일을 이용하는 메모리 맵 파일 파일 매핑 오브젝트가 생성되고 프로세스의 주소 공간에 이에 대한 뷰가 매핑되고 나면 메모리 영역 을 통해 이 공간에 접근할 수 있게 된다. 만일 다른 프로세스와 데이터를 공유하려 한다면 CreateFileMapping 함수를 호출할 때 pszName 매개변수로 커널 오브젝트의 이름을 나타내는 문자열을 전달하면 된다. 공유된 데이터에 접근하고자 하는 프로세스는 CreateFileMapping이나 OpenFileMapping 함수를 호출할 때 동일한 커널 오브젝트 이름을 사용하면 된다. 만일 파일 매핑 오브젝트를 더 이상 사용할 필요가 없게 되면 CloseHandle 함수를 호출해야 한다. 해당 오브젝트를 참조하는 모든 핸들이 닫히게 되면 시스템은 페이징 파일 내의 커밋된 저장소를 해 제하게 된다.
  • 30. 10. 스파스 메모리 맵 파일 555쪽 “언제 물리적 저장소를 디커밋 하는가” 에서 논의했던 표계산 프로그램 • 만일 CELLDATA 구조체의 크기가 128 바이트라면 이 배열은 6.553.600(200 X256 X128)바이트의 물리적 저장소를 필요로 한다. • CreateFileMapping 함수의 fdwProtect 매개변수 로 SEC_RESERVE 나 SEC_COMMIT 플래그를 지정하면 물리적 저장소의 예약과 커밋을 분리하여 수행할 수 있다. • CreateFileMapping 함수를 호출할 때 SEC_COMMIT 플래그를 사용하면 시스템의 페이징 파일 내에 저장소를 커밋해 준다. • CreateFileMapping 함수를 호출할 때 SEC_RESERVE 플래그를 사용하면 시스템은 시스템 페이징 파일로부터 물리적 저장소를 커밋하지 않은 상태로 파일 매핑 오브젝트의 핸들을 반환한다.
  • 31. 10. 스파스 메모리 맵 파일 공유된 영역에 대한 물리적 저장소를 커밋하려면 VirtualAlloc 함수를 호출하면된다. VirtualAlloc 함수를 호출하여 메모리 맵 뷰 영역에 물리적 저장소를 커밋하는 것은 MEM_RESERVE 플래그를 이용하여 VirtualAlloc 함수를 호출하여 특정 영역을 예약한 후, 또 다시 VirtualAlloc 함수를 호출하여 물리적 저장소를 커밋하는 과정과 매우 흡사하다. VirtuaAlloc 함수를 이용하여 예약된 영역에 대해 일부분만을 커밋할 수 있는 것과 같이 MapViewOfFile 이나 MapViewOfFileEx 함수를 호출하여 예약된 영역에 대해 VirtuaAlloc 함수를 호출하여 일부분만을 물리적 저장소로 커밋할 수 있다.

Editor's Notes

  1. . exe 파일이 프로세스의 주소 공간에 매핑되고 나면 시스템은 .exe 파일 내의 코드에서 사용하고 있는 함수들을 구현하고 있는 DLL 파일들의 목록을 가져온다. 그 후 각 DLL 파일들에 대해 LoadLibrary 함수를 반복적으로 호출한다. 만일 로드하는 DLL 파일이 또 다른 DLL 파일을 필요로 히는 경 우 이 파일들에 대해서도 LoadLibrary를 호출한다. 각각의 DLL 파일에 대해 LoadLibrary가 호출될 때마다 앞서 설명한 4, 5번의 절차와 유사한 작업이 반복적으로 수행된다.
  2. 실제로 실행 파일의 내용은 여러 개의 섹션으로 구분된다. 코드를 위한 섹션도 존재하며, 전역변수를 위한 섹션도 존재한다. 각각의 섹션들은 페이지 경계에 맞게 정렬되어 있다. 애플리케이션은 GetSystemlnfo 함수를 호출하여 현재 시스템의 페이지 크기를 확인할 수 있다 . exe나 DLL 파일 내에서는 코드 이 데이터섹션 앞쪽에 위치한다.
  3. (시작)만일 특정 인스턴스가 데이터 페이지에 위치하고 있는 전역변수의 값을 변경하게 되면, 동일 애플리케이션의 모든 인스턴스의 메모리 내용이 변경되는데 이처럼 변경 작업이 일어나게 되면 큰문제를 유발하게 될 것이므로 절대로 이와 같이 동작되어서는 안 된다. 시스템은 메모리 관리 시스템의 카피 온 라이트 기능을 이용하여 이 같은 변경 작업이 일어나지 않도록 하고 있다. 애플리케이션이 메모리 맵 파일의 내용을 변경하려고 시도하게 되면 시스템은 변경 시도를 사전에 감지하여 가상 메모리에 새로운 블록을 할당하고 애플리케이션이 변경하려고 시도했던 페이지의 내용을 복사한다. 애플리케이션은 복사 작업이 완료된 이후에야 비로소 새롭게 할당된 메모리 블록에 대해 변경을 수행할 수 있게 된다. 결국 동일 애플리케이션의 다른 인스턴스에는 어떠한 영향도 주지 않게 된다. (끝)시스템은 가상 메모리에 새로운 페이지를 할당하고 데이터 페이지 번의 내용을 복사한다. 첫 번째 인스턴스의 주소 매핑 정보를 변경하여 이전 주소를 이용하여 메모리에 접근을 시도하는 경우 새로운 페이지에 접근하도록 한다. 이제 프로세스가 전역변수의 내용을 변경한다 하더라도 동일 애플리케이션의 다른 인스턴스에는 영향을 주지 않게 된다. 이러한 절차는 애플리케이션을 디버깅할 때에도 동일하게 일어난다. 동일 애플리케이션을 여러 변 수행하고 그중하나의 인스턴스에 대해 디버깅을 수행하려 한다고치면, 디버거에서 소스 코드의 특정라인에 브레이크 포인트를 설정하면 디버거는 브레이크 포인트를 설정한 소스 코드에 해당하는 어셈블리 명령을 변경하여 애플리케이션이 수행을 중단하고 디버거로 제어권을 반환하도록 한다. 이 경우 앞서 알아본 것과 같은 동일한문제가 발생할수 있다. 즉 디버거가 코드를 수정하면 애플리케이션의 모든 인스턴스의 코드가 수정되고 이는 어떤 인스턴스든지 브레이크 포인트를 설정한 위치까지 수행되기만 하면 디버거로 제어권이 반환되게 될 것이다. 앞서와 마찬가지로 이러한 문제 상황을 극복하기 위해 시스템은 메모리에 대한 카피 온 라이트를 수행한다. 디버거가 코드를 수정하려 고 시도하면 시스템은 먼저 그 사실을 감지하고 새로운 메모리 블록을 할당한 후 이전 페이지의 내용을 복사한다. 이후 디버거는 새로운 페이지의 내용을 수정하게 된다.
  4. (끝)예제에서는 하나의 변수만이 섹션 내에 추가된다. 변수 초기화 구문 이후에 나타나 있는 #pragma data seg 행은 더 이상 Shared 섹션 내에 초기화된 변수를 추가하지 말 것을 일걷는 것이며 이 문장 이후에 나타나는 변수들은 기본 데이터 섹션에 추가되게 된다. 이같은 구문을 사용할 경우 컴파일러는 초기화된 변수만을 새로운 섹션에 추가한다는 점에 주의해야 한다.
  5. (시작)예를 들어 앞의 코드에서 초기화 구분을 제거해 버리게 되면 다음 코드와 같이 컴파일러는 Shared 섹션이 아닌 다른 섹션에 변수를 추가하게 된다.
  6. 이 방법은 구현하기는 상당히 쉽지만 중요한 두 가지 단점이 있다. 첫째로 파일 크기만큼의 메모리를 할당해야만 한다. 파일 크기가 작은 경우 문제가 되지 않겠지만 파일이 2GB라면 어떻게 될 것인가? 32 비트 시스템에서 수행되는 애플리케이션은 이처럼 큰 물리적 저장소를 커밋할 수 없다. 파일 의 크기가 이처럼 큰 경우라면 다른방법을 고려해야만 할 것이다. 둘째로, 메모리에서 파일의 내용을 뒤집은 후 그 내용을 다시 파일로 저장하는 동안에 수행이 중단되면 기존 파일의 내용이 손상된다. 이러한 문제를 해결하는 가장 간단한 방법은 이전 파일의 내용을 미리 복사해 두고, 전체 과정이 완전히 완료된 이후에 파일의 복사본을 삭제하는 것이다. 불행히도 이와 같은 방법을 시용하려면 추가적인 디스크공간이 펼요하다.
  7. (끝)이 방법은 첫 번째 방법에 비해 구현하기가 좀 더 복잡하다. 하지만 8KB의 메모리 공간만 할당하면 되기 때문에 메모리를 좀 더 효율적으로 사용한다는 장점이 있다. 그럼에도 불구하고 이 방법 또한 두 가지 큰 문제점이 있다. 첫째로 파일의 내용을 읽을 때마다 파일 포인터를 이동해야 하기 때문에 첫 번째 방법에 비해 작업 수행 속도가 느려질 수 있다. 둘째로, 하드 디스크의 공간을 많이 사용할 가능성이 있다. 만일 기존파일의 크기가 1GB 라면, 작업이 진행되는 동안 새롭게 생성되는 파일도 그 크기가 1GB까지 증가될 것이며, 기존 파일을 삭제하기 전까지는 총 2GB 의 디스크 공간을 점유하게된다. 즉 1GB 의 추가적인 디스크공간이 필요한 것이다. 이러한 단점을 극복하기 위해 세 번째 방법을 고려하게 되었다.
  8. 두 번째와 세 번째 방법을 비교해 보면, 세 번째 방법이 하드 디스크의 공간을 효율적으로 사용한다는 측면에서는 더 뛰어나다고 할 수 있다. 세 번째 방법은 동일한 파일에 대해 읽기 작업과 쓰기 작업을 수행하기 때문에 추가적인 디스크 공간을 필요로 하지 않는다. 메모리 사용 측면에서도 그 다지 나쁘지 않은데, 단지 16KB 정도의 공간만을 사용할 뿐이다.
  9. 이 방법은 파일에 대한 캐싱 작업을 시스템이 직접 수행해 주기 때문에 상당한 이점이 있다. 사용자는 메모리를 할당할 필요도 없고, 데이터 파일을 메모리로 읽어오거나, 파일로 쓰는 작업, 메모리 블록을 해제하는 등의 작업을 전혀 수행할 필요가 없다. 하지만 전원이 차단되는 것과 같은 갑작스러운 중단 사태가 발생하게 되면 데이터가 소실될 가능성이 있기는 하다.
  10. 각 단계별 함수 사용법이 책이 기재되어 있으나 따로 설명하지 않음. 614p에 관련 내용이 있음.
  11. 이 예제는 64KB(할당 단위 크기) 혹은 그보다 작은 크기로 뷰를 매핑한다. MapViewOfFile 함수를 호출할 때에는 항상 할당 단위 크기의 배수로 파일의 위치를 지정해야 한다는 점에 유념해야 한다고 함. 각각의 뷰를 주소 공간에 매핑하고 0의 개수를 세어본 직후가 파일 매핑 오브젝트를 닫기 위한 가정 적절한시점이다.
  12. (1문단끝나고)이것이 가능한 이유는 단일 프로세스의 서로 다른 가상 주소 공간에 서로 다른 뷰를 매핑하는 경우라 하더라도 실제로는 단일의 램 페이지들에만 파일의 데이터가 유지되기 때 문이다. 이러한 특성은 서로 다른 프로세스들 사이에서도 동일하게 적용되는데 단일의 파일 매핑 오브젝트에 대해 여러 개의 뷰를 서로 다른 프로세스 주소 공간 상에 각각 매핑하는 경우에도 데이터 파일은 단일의 램 페이지들을 이용하여 유지될 것이기 때문에 그 내용은 일관되게 유지될 수 있다. 이러한 특성을 바꾸어 말하면 각 프로세스들의 독립주소 공간에 동일한 램 페이지들이 매핑될 수 있음을 의미한다. (끝)파일을 읽기 전용으로 다루는 경우에도 일관성 문제는 발생하지 않을 것이며, 이 또한 메모리 뱀을 이용하기에 아주 적합한 경우라고 할 수 있다. 네트워크로 연결된 원격지에 있는 쓰기 가능한 공유 파 일은 메모리 맵 파일로 사용하지 않는 것이 좋다. 만일 이러한 파일을 메모리 맵 파일로 사용하게 되면 시스템은 파일 데이터에 대한 일관성을 유지하지 못한다. 특정 프로세스가 원격 머신에서 공유된 파일의 내용을 변경한 경우 다른 머신에서는 공유된 파일의 변경사항을 알지 못하여, 이로 인해 메 모리 상에 변경되기 이전의 데이터를 가지고 있게 된다.
  13. pvBaseAddress로는 파일을 매핑하고자 하는 메모리의 시작 주소를 전달하면 된다. VirtualAlloc 함수에서와 마찬가지로 이 주소는 반드시 할당 단위 경계 (64KB)의 배수여야 하며, 그렇지 않을 경우 Map ViewOfFileEx 함수는 NULL을 반환하며 이때 GetLastError를 호출해 보면 1132(ERROR_MAPPED_ALIGNMENT)를 가져오게 된다. 지정한 시작 주소에 매핑을 수행할 수 없는 경우(예를들어 파일이 너무 크거나 해당 시작 주소로부터 파일을 매핑할 만큼의 충분한 공간을 예약할 수 없는 경우)에도 이 함수는 NULL을 반환한다. MapViewOfFileEx함수는 해당 파일을 매핑할 수 있는 적절한 다른 영역을 찾아보지 않는다. 물론 pvBaseAddress 매개변수로 NULL을 지정하면 시스템이 적절한 다른 공간을 찾도록 할 수 있으며, 이 경우 MapViewOfFile함수와 완전히 동일하게 동작하게 된다. Map ViewOfFileEx 함수는 다수의 프로세스 간에 메모리 맴 파일을 공유하는 경우에 유용하게 사용될 수 있다. 예를 들어 파일 내의 자료구조가 다른 자료구조를 가리키는 포인터를 가지고 있고, 둘 이상의 프로세스들 사이에 이러한 데이터들을 공유해야 할 경우 동일한 주소공간에 해당파일을 매핑해야 할 필요가 있다. 링크드 리스트가 아주 좋은 예가 될 수 있는데, 링크드 리스트를 구성하는 각 항목이나 요소들은 다른 항목이나 요소를 가리키는 주소 값을 가지고 있게 된다. 리스트를 순회하기위해서는 리스트 내의 첫 번째 항목의 주소를 알고 있어야 하며, 첫 번째 항목은 다음 항목의 위치를가리키는 주소를 가지고 있게 된다. 이와 같은 자료구조를 메모리 맵 파일에 저장하게 되면 문제가 발생할 수 있다. 특정 프로세스가 메모리 맵 파일에 링크드 리스트를 구성하고, 이를 다른 프로세스와 공유한다고 하면, 새로운 프로세스의 경우 해당 메모리 맵 파일을 전혀 다른 주소 공간 상에 매핑할 수 있다. 이때 이 프로세스 내에서 리스트를 순회하기 위해 첫 번째 항목에 대한 정보를 얻은 후 다음 항목을 가리키는 메모리 주소를 가져오는 경우 획득된 주소 값은 올바르지 않은 위치를 가리키는 값이 될 것이다. 이러한 문제를 해결하기 위한 두 가지 방법이 있다. 첫 번째 방법은 새로 생성된 프로세스가 링크드 리스트를 포함하고 있는 메모리 맵 파일을 자신의 주소 공간에 매핑할 때 MapViewOfFile 함수 대신 MapViewOfFileEx 함수를 사용하는 것이다. 물론 이 방법을 사용하려면 새로 생성된 프로세스가 링크드 리스트를 공유하고자 했던 이전 프로세스에서 메모리 뱀 파일이 어느 주소에 매핑되었었는지를 알고 있어야 한다. 만약 프로세스 간에 상호 통신할 수 있는 방법이 구성되어 있는 경우라면 아무런 문제가 없다. 매핑된 주소 값은 양쪽 프로세스에서 각기 하드코딩될 수도 있으며, 윈도우 메시지 전송 방식과 같은 프로세스간 통신 방법을 이용하여 다른 프로세스에게 그 주소를 알려줄 수도 있다. 이 문제를 해결하는 두 번째 방법은 프로세스가 링크드 리스트에 노드를 삽입할 때 다음 노드가 위치하고 있는 곳의 주소를 시작 주소로부터의 오프셋을 이용하여 저장하는 것이다. 이러한 방법을 사용 하려면 애플리케이션은 각각의 노드에 접근할 때마다 메모리 맵 파일의 시작 주소에 오프셋 값을 더하여 노드에 접근해야 한다. 이전의 방식에 비해 느릴 수도 있고 노드의 위치를 계산하는 코드를 추가적으로 포함해야 하기 때문에 프로그램의 크기도 더욱 커질 것이며, 에러가 발생할 가능성도 높아질 것이기 때문이다. 이러한 문제점이 있긴 하지만, 이러한 방법은 명백히 동작 가능한 유용한 방법이며 마이크로소프트 컴파일러는 이를 위해 __based 키워드를 제공하고있다.
  14. 코드가 길어서 잘랐음.
  15. 이 예제에서는 MapViewOfFile 함수를 두 변 호출하여 시스템이 서로 다른 주소 공간을 예익 하도록하였다. 첫 번째 영역의 크기는 파일 매핑 오브젝트의 크기와 동일하며, 두 번째 영역의 크기는 파일 매핑 오브젝트의 크기에서 64KB만큼을 뺀 크기이다. 두 영역이 서로 분리되어 있고, 영역이 서로 겹치지 않음에도 불구하고 동일 파일 매핑 오브젝트를 이용하여 생성한 뷰들 사이에서는 데이터의 일관성이 유지된다.
  16. (시작)지금까지 메모리 맵 파일에 대해 얘기하는 동안에는 시스템이 디스크 상의 데이터 파일이나 시스템 페이징 파일 내의 메모리 맵 파일 전체를 커밋했었다. 이는 물리적 저장소를 우리가 원하는 만큼 효과적으로 사용할 수 없음을 의미한다. 555쪽 “언제 물리적 저장소를 디커밋 하는가” 에서 논의했던 표계산 프로그램에서 표의 내용 전체를 다른 프로세스와 공유하고 싶을 경우 만약 메모리 맵 파일을 사용하는 경우라면 전체 표의 내용에 대해 물리적 저장소를 커밋해야 할 것이다. 만일 CELLDATA 구조체의 크기가 128 바이트라면 이 배열은 6.553.600(200 X256 X128)바이트의 물리적 저장소를 필요로 한다. 이와 같이 표의 전체 구간에 메모리를 할당하기 위해 페이징 파일로부터 물리적 저장소를 할당하는 것은 너무 과도하다고 할 것이며 대부분의 사용자가 이 중 일부분의 셀만을 사용할 것이므로 나머지 공간은 사용되지 않고 남게 될 것이다“ 따라서 파일 매핑 오브젝트를 이용하여 표를 공유하고자 하는 경우 물리적 저장소 전체를 미리 커밋하는 것은 그다지 좋은 방법이 아니다. CreateFileMapping 함수의 fdwProtect 매개변수 로 SEC_RESERVE 나 SEC_COMMIT 플래그를 지정하면 물리적 저장소의 예약과 커밋을 분리하여 수행할 수 있다. 이러한 플래그 값들은 시스템 페이징 파일을 이용하는 파일 매핑 오브젝트를 생성하는 경우에만 사용 될 수 있다. CreateFileMapping 함수를 호출할 때 SEC_COMMIT 플래그를 사용하면 시스템의 페이징 파일 내에 저장소를 커밋해 준다. 이 경우 fdwProtect 매개변수로 어떤 플래그도 지정하지 않았을 때와 동일한 작업이 수행된다. CreateFileMapping 함수를 호출할 때 SE_ RESERVE 플래그를 사용하면 시스템은 시스템 페이징 파일로부터 물리적 저장소를 커멋하지 않은 상태로 파일 매핑 오브젝트의 핸들을 반환한다. 이렇게 하면 MapViewOfFile 이나 Map ViewOfFileEx 함수를 호출하여 이러한 파일 매핑 오브젝트에 대한 뷰를 생성하면 프로세스의 주소공간상에 영역을 예약하기는 하지만 이 영역에 대한 어떠한 물리적 저장소도 커밋하지 않습니다. 따라서 스레드가 이 영역에 접근을 시도하게 되면 접근 위반을 유발하게 될 것이다. 이 단계에서 우리가 가지고 있는 것은 주소 공간 내에 예약된 영역과 각 영역을 구분하기 위한 파일 매핑 오브젝트를 가리키는 핸들 값 정도입니다.. 다른 프로세스 또한 동일한 파일 매핑 오브젝트를 자신의 주소 공간의 동일 영역에 매핑할 수 있을 댄데 이 경우에도 물리적 저장소는 여전히 커밋되지 않은 상태로 유지되며, 예약된 영역 내의 뷰를 통해 접근을 시도하게 되면 접근위반을 유발하게 됩니다.
  17. 공유된 영역에 대한 물리적 저장소를 커밋하려면 VirtualAlloc 함수를 호출하면된다. VirtualAlloc 함수를 호출하여 메모리 맵 뷰 영역에 물리적 저장소를 커밋하는 것은 MEM_RESERVE 플래그를 이용하여 VirtualAlloc 함수를 호출하여 특정 영역을 예약한 후,또 다시 VirtualAlloc 함수를 호출하여 물리적 저장소 를 커밋하는 과정과매우흡사하다. VirtuaWloc 함수를 이용하여 예약된 영역에 대해 일부분만을 커밋할 수 있는 것과 같이 MapViewOfFile 이나 MapViewOfFileEx 함수를 호출하여 예약된 영역에 대해 VirtuaAlloc 함수를 호출하여 일부분만을 물리적 저장소로 커밋할 수 있다. 일단 이처럼 물리적 저장소가 커밋되고 나면 동일 파일 매밍 오브젝트에 대한 뷰를 매핑하고 있던 다른 프로세스들은 모두 성공적으로 커밋된 페이지에 접근할 수 있게 된다. SEC_RESERVE 플래그와 VirtualAlloc 함수를 사용하면 표계산 애플리케이션의 CellData 가 점유하고 있는 물리적 저장소를 매우 효과적으로 사용하면서도 다른 프로세스와 공유할 수 있게 된다.