{{위키데이터 속성 추적}}
'''메모리 맵 파일'''(Memory mapped file, '''MMF''', 메모리 사상 파일)은 [[운영 체제]]에서 [[파일]]을 다루는 방법 중 하나이다. 물리 디스크 파일, 장치, [[공유 메모리 객체]]와 같이 운영 체제에서 [[파일]]로 다루는 모든 대상에 대해서 사용 가능하며, 메모리 맵 파일을 통해 [[프로세스]]의 [[가상 메모리]] 주소 공간에 파일을 매핑한 뒤 [[가상 메모리]] 주소에 직접 접근하는 것으로 파일 읽기/쓰기를 대신한다.

기본 파일 입출력 API에 비해서 저렴한 비용을 사용하여 파일의 내용에 접근할 수 있도록 해 주며, 메모리와 파일 간의 자료 전송은 [[운영 체제]]가 자동으로 처리하므로 보다 간단하게 사용할 수 있다. 다른 프로세스에서 동일한 파일에 메모리 맵 파일을 이용하여 접근할 경우 [[공유 메모리]]처럼 사용하는 것도 가능하다.

== 구조 ==
메모리 맵 파일을 사용하면 디스크에 있는 파일의 블록들과 프로세스의 [[페이지]]가 연결된다. 이 상태에서는 가상 메모리에 사상만 되어 있을 뿐이며, 실제 메모리에 파일을 불러오는 시기는 해당 주소에 읽거나 쓰기 작업을 시도할 때 이루어진다. 이 작업은 운영 체제에서 가상 메모리를 다루는 데 사용하는 [[페이징]] 기법과 같이 [[페이지 부재]]를 일으키는 방식을 이용한다. 일반적으로 파일에서 불러오는 자료는 페이지 크기와 같은 4KiB이지만, 몇몇 운영 체제에서는 [[하드디스크]]의 낮은 [[임의 접근 시간]]을 고려해 4KiB보다 많은 자료를 [[페이지]]로 올릴 수도 있다.

이 때문에 메모리 맵 파일로 작업 중인 데이터가 실제 파일로 바로 반영되지는 않으며, [[페이지 교체 알고리즘]]에 따라 해당 페이지가 메모리에서 내려갈 경우, 또는 메모리 맵 파일을 닫는 과정에서 반영된다. 이것은 메모리 맵 파일과 파일 입출력 API를 동시에 사용할 때 문제가 되는데, 메모리 맵 파일을 통해 변경된 자료는 즉시 반영되지 않으므로 그 지점에 해당하는 자료를 파일 입출력 API를 사용하여 읽어오려 할 때 [[동기화]] 문제가 발생하게 된다. 따라서 메모리 맵 파일을 사용할 때에는 읽기 전용으로만 사용하는 목적이 아닌 이상 파일 입출력 API를 사용하지 않는 것이 좋다.

오른쪽 위의 예제 그림은 메모리 맵 파일을 사용할 때 프로세스의 [[가상 주소]]와 [[물리 주소]], 그리고 파일들의 관계를 알 수 있다. 각 블록은 [[페이지]] 단위로 나타낸 것이다. 예제에서는 프로세스 2개와 파일 2개가 나오며, 이중 b2는 메모리 맵 파일의 공유를, b3는 사상이 되었으나 아직 메모리에 적재되지 않은 것을 나타낸다..

== 장점 ==
직접적인 파일 입출력을 수행할 필요가 없다. 메모리 맵 파일을 사용하면 파일 내용이 메모리 주소에 사상되므로 파일을 모두 불러온 것처럼 메모리 주소를 이용하여 연산 작업을 할 수 있어 코드가 깔끔해지고 유지보수가 편해진다.

[[버퍼]]나 파일 처리를 위한 추가적인 [[자료 구조]]가 필요 없다. 운영 체제에서 [[페이징]] 기법을 사용하여 파일의 내용을 관리하며, 페이지 크기(보통 4KiB)에 따라 적절히 파일의 내용을 읽고 쓸 수 있으며 파일 반영(flush) 작업도 수행해준다.

대용량의 자료를 처리할 때도 매우 효율적이다. 파일에 접근할 때 [[지연 적재]]를 이용하므로, 파일의 크기가 매우 크더라도 필요한 부분만 파일에서 불러와 작업할 수 있으며, 작업이 끝난 데이터는 자동으로 파일에 반영된다.

전통적인 파일 입출력 API보다 속도가 빠르다. API는 [[시스템 호출]]을 사용하기 때문에 작업을 수행하는 동안 유저 모드와 커널 모드를 전환하는 데 필요한 인터럽트가 오버헤드로 작용하게 된다. 메모리 맵 파일은 4KiB 단위로 자료를 미리 불러올 때 발생하는 [[페이지 부재]]외의 모든 작업이 실제 메모리상에서 이루어지므로 대부분 파일 API를 통한 파일 처리보다 빠르다.<ref>[http://developers.sun.com/solaris/articles/read_mmap.html Oyetunde Fadele(2002), "A Performance Comparison of "read" and "mmap" in the Solaris 8 OS", ''Sun Developer Network''.]</ref>

== 단점 ==
POSIX와 윈도에서 파일의 크기(즉, [[EOF]]의 위치)를 변경할 수 없다. 파일 입출력 API에서는 간편한 방법으로 파일의 크기를 변경하는 방법을 제공한다.<ref>[http://pubs.opengroup.org/onlinepubs/007904975/functions/write.html "write", ''The Open Group''.]</ref> 메모리 맵 파일은 파일의 크기를 바꿀 수는 없으며 메모리 맵 파일을 사용하기 이전, 또는 이후에만 파일의 크기를 바꿀 수 있다.<ref>[http://www.gnu.org/s/hello/manual/libc/File-Size.html "File Size",''The GNU C Library''.]</ref>

메모리 맵 파일을 이용한 접근은 최적의 파일 접근 방식은 아니다. 파일 입출력 API를 사용한 방법이 API의 오버헤드인 것에 비해 메모리 맵 파일에서는 [[페이지 부재]]중의 데이터 전송 시간이 오버헤드로 작용한다.<ref>[http://lists.freebsd.org/pipermail/freebsd-questions/2004-June/050371.html Matthew Dillon(2004),"read vs. mmap (or io vs. page faults)".''freebsd.org Mailing Lists''.]</ref> 따라서 [[데이터베이스]]와 같이 파일을 읽고 쓰는데 오버헤드를 최소로 줄인 자료구조와 알고리즘과 메모리 맵 파일을 비교할 때 오히려 메모리 맵 파일이 느릴 수도 있다.

크기가 지나치게 큰 파일을 처리하는 데 어려움이 있다. [[IA-32]] 기반 시스템에서 하나의 프로세스에서 [[물리 주소 확장|PAE]] 기술을 사용하지 않고 사용 가능한 최대 크기는 4GB로 제한된다.<ref>{{웹 인용 |url=http://www.intel.com/content/dam/doc/manual/64-ia-32-architectures-software-developer-vol-1-manual.pdf# |제목=Intel,"3.3 Memory Organization",''Intel® 64 and IA-32 Architectures Software Developer’s Manual Volume 1: Basic Architecture''. |확인날짜=2011-12-05 |보존url=https://web.archive.org/web/20110922030615/http://www.intel.com/content/dam/doc/manual/64-ia-32-architectures-software-developer-vol-1-manual.pdf# |보존날짜=2011-09-22 |url-status=dead }}</ref> 따라서 프로세스의 메모리 주소를 사용하는 메모리 맵 파일이 한번에 다룰 수 있는 크기는 이보다 작아지며, 이 크기를 넘어가는 파일을 메모리 맵 파일로 다루려 할 때 계산이 복잡해질 수 있다.

== 용도 ==
대부분 운영 체제에서는 [[프로세스]]를 실행할 때 [[실행 파일]]의 각 [[메모리 세그먼트|세그먼트]]를 메모리에 사상하기 위해 메모리 맵 파일을 이용한다. 이 경우 하나의 프로세스가 동시에 여러 번 동작할 때 실행 코드와 같은 읽기 전용 세그먼트를 공유할 수 있어 중복된 내용만큼의 메모리를 절약할 수 있다. 그리고 메모리 맵 파일이 가지는 [[지연 적재]] 특징 덕분에 [[실행 파일]]에서 사용하지 않는 부분이 있을 때도 메모리를 최적화하여 사용할 수 있다.

또한, 파일의 내용이 [[프로그래밍 언어]]에서 직접 다룰 수 있는 [[구조체]]와 같은 형식을 가지고 작성되어 있으면, 메모리 맵 파일을 이용해 자료에 바로 접근하는 방법을 사용하기도 한다. 이 경우 위에 서술한 바와 같이 많은 장점을 얻을 수 있다.

또 다른 사용 용도는 [[프로세스 간 통신]] 수단이다. 현대의 [[운영 체제]]에서는 하나의 [[프로세스]]는 고유의 메모리 주소만 갖게 되어 다른 [[프로세스]]의 메모리에 접근할 수 없다. 따라서 [[프로세스 간 통신]]을 위해 [[공유 메모리]]를 사용하는 방법이 고안되어 있으며 메모리 맵 파일은 이 [[공유 메모리]]를 사용하는 방법이 될 수 있다.

== 지원 사항 및 예제 ==
=== POSIX ===
[[POSIX]]에서는 [[mmap]]이라는 함수를 통해 메모리 맵 파일 기능을 제공하고 있다. <code>MAP_SHARED</code>라는 플래그를 통해 다른 프로세스에서 같은 파일에 대해 메모리 맵 파일 기능을 사용할 수 있도록 할 수 있어 공유 메모리로도 사용할 수 있다.<ref>[http://pubs.opengroup.org/onlinepubs/7908799/xsh/mmap.html "mmap", ''The Open Group''.]</ref><ref>그러나 본래의 공유 메모리 기능은 [http://pubs.opengroup.org/onlinepubs/007908799/xsh/shmat.html shmap함수]를 통해 지원되고 있으므로 구분이 필요하다.</ref> [[POSIX]]를 따르는 운영 체제들([[리눅스]], [[유닉스]], [[솔라리스 (운영 체제)|솔라리스]] 등)에서는 약간의 차이는 있지만 같은 기능과 특징을 가진 메모리 맵 파일 기능을 제공한다.<ref>[http://www.joinc.co.kr/modules/moniwiki/wiki.php/man/2/mmap 예제]</ref>

=== 윈도 ===
[[윈도우 API]]에서는 CreateFileMapping() 함수와 MapViewOfFile()를 통해 메모리 맵 파일 기능을 제공하고 있다.<ref>[http://msdn.microsoft.com/en-us/library/windows/desktop/aa366537%28v=vs.85%29.aspx Microsoft,"CreateFileMapping function",''Microsoft Developer Network''.]</ref><ref>[http://msdn.microsoft.com/en-us/library/windows/desktop/aa366761%28v=vs.85%29.aspx Microsoft,"MapViewOfFile function",''Microsoft Developer Network''.]</ref>
POSIX를 따르는 다른 운영 체제와는 달리 [[마이크로소프트 윈도우|윈도우]]에서는 [[공유 메모리]]를 메모리 맵 파일을 통해서만 사용할 수 있다.
([http://msdn.microsoft.com/ko-kr/library/ms810613.aspx 예제])

=== 언어별 지원 ===
* [[자바 (프로그래밍 언어)|자바]]에서는 [http://docs.oracle.com/javase/7/docs/api/java/nio/channels/FileChannel.html <code>FileChannel</code> 클래스]를 통해 메모리 맵 파일 기능을 제공한다.
* [[마이크로소프트]] [[닷넷 프레임워크]]에서는 [http://msdn.microsoft.com/en-us/library/dd997372.aspx <code>MemoryMappedFile</code> 클래스]를 통해 메모리 맵 파일을 제공하고 있다.
* [[파이썬]]에서는 [http://docs.python.org/library/mmap.html <code>mmap</code> 클래스]를 통해 메모리 맵 파일을 제공하고 있다. 다만, 윈도와 POSIX 기반 운영 체제에서 [[클래스 (컴퓨터 과학)|클래스]] 구조가 다르므로 주의가 필요하다.
* [[Boost]]에서도 메모리 맵 파일기능을 제공한다.<ref>[http://www.boost.org/doc/libs/1_47_0/libs/iostreams/doc/classes/mapped_file.html "Memory-Mapped Files",''Boost C++ Libraries''.]</ref><ref>[http://www.boost.org/doc/libs/1_48_0/doc/html/interprocess/sharedmemorybetweenprocesses.html#interprocess.sharedmemorybetweenprocesses.mapped_file 예제]</ref>

== 같이 보기 ==
* [[메모리 맵 입출력]] - 메모리 맵 파일과 차이를 주목할 것
* [[mmap]] - [[POSIX]]에서 [[메모리 맵 입출력]]과 메모리 맵 파일 기능을 지원하는 함수
* [[페이징]]

== 참고 문헌 ==
* Silberschatz, 조유근 등 공역(2008), 『Operating System Concepts』 7판, 9.7 「메모리 사상 파일」, 홍릉과학출판사.
* Johnson M. Hart, 류광 역(2011), 『Windows 시스템 프로그래밍』 제4판, 제5장 「메모리 관리, 메모리 맵드 파일, DLL」, 정보문화사.

== 각주 ==
{{각주}}

[[분류:가상 메모리]]