본문으로 이동
  • 현재 모든 문서는 작성 중입니다. 보시는 데 불편함이 있더라도 양해 부탁드립니다.

운영체제 기본/가상 메모리: 두 판 사이의 차이

~ldmsys
총론 보강: 주소·매핑의 수명, 파일 매핑의 독립 참조와 공유
BIOS GRUB 부팅 경로 보강과 각론 형식 통일
 
(같은 사용자의 중간 판 5개는 보이지 않습니다)
1번째 줄: 1번째 줄:
[[운영체제 기본|목차]] · 이전: [[운영체제 기본/프로세스와 스레드|프로세스와 스레드]] · 다음: [[운영체제 기본/파일과 입출력|파일과 입출력]]
[[운영체제 기본|목차]] · 이전: [[운영체제 기본/동시성|동시성]] · 다음: [[운영체제 기본/파일과 입출력|파일과 입출력]]


포인터에 들어 있는 주소를 RAM의 물리적 위치로 생각하면, 서로 다른 프로세스가 같은 주소를 사용하는 상황을 설명하기 어렵다. 이 장에서는 MMU가 있는 일반적인 Linux PC·서버를 기준으로 가상 주소와 물리 메모리를 구분한다.
프로그램은 배열과 포인터를 연속된 주소로 다루지만, 실제 RAM은 여러 프로그램이 나누어 쓰는 유한한 자원이다. 프로그램마다 필요한 크기도, 실행되는 시간도 다르다. 가상 메모리는 프로그램이 사용하는 주소와 실제 저장 위치 사이에 변환 계층을 두어 배치, 보호, 공유를 함께 다루는 설계다. 여기서는 주소 변환 하드웨어가 있는 시스템의 페이지 기반 방식을 설명한다.


== 주소 변환 ==
== 배치의 자유와 보호를 함께 얻기 ==
프로그램이 사용하는 것은 자기 주소 공간의 가상 주소다. 커널은 가상 주소와 물리 페이지의 매핑을 관리하고, CPU의 MMU는 이를 이용해 주소를 변환한다. 주소 변환을 할 때마다 시스템 호출을 하는 것은 아니다.
프로그램이 물리 주소를 직접 사용한다면 실행 위치가 바뀔 때 주소를 조정해야 한다. 한 프로그램의 배열이 커질 때 바로 뒤의 공간을 다른 프로그램이 차지하고 있을 수도 있다. 빈 공간의 총량이 충분해도 작은 조각으로 흩어져 있으면 큰 연속 영역을 배치하기 어렵다. 잘못 계산한 포인터가 다른 프로그램의 데이터를 덮어쓰는 문제도 별도로 막아야 한다.


매핑에는 어느 물리 메모리를 가리키는지뿐 아니라 어떤 접근을 허용할지에 관한 정보도 들어간다. 읽을 수 있는 영역이 반드시 쓸 수 있는 영역은 아니다. 서로 다른 프로세스의 같은 가상 주소가 다른 물리 페이지로 연결될 수 있고, 공유 메모리처럼 같은 물리 페이지에 연결될 수도 있다.
가상 메모리는 각 프로세스에 독립적인 주소 공간을 제공한다. 같은 주소 값이라도 어느 주소 공간에서 사용되는지에 따라 다른 물리 메모리를 가리킨다. 프로그램은 자기 주소를 유지하고, 운영체제는 그 주소에 연결할 물리 메모리를 선택한다. 접근 권한도 이 연결에 포함하므로 읽기 전용 영역에 대한 쓰기나 허용되지 않은 주소의 접근을 하드웨어가 가려낼 수 있다. 배치의 자유를 얻는 동시에 프로그램 사이의 경계를 강제하는 것이다.


== 주소 공간을 확보하는 것과 RAM을 쓰는 것 ==
== 페이지 단위의 간접 참조와 그 비용 ==
프로그램이 가상 주소 범위를 확보했다고 그 크기만큼 RAM이 즉시 채워지는 것은 아니다. 매핑의 종류와 접근 여부에 따라 필요한 시점에 페이지를 마련할 수 있다. <code>malloc()</code>도 libc의 메모리 할당기이므로, 호출할 때마다 커널에서 새 메모리를 가져오는 것으로 이해하면 안 된다.
페이징은 가상 주소 공간과 물리 메모리를 일정한 크기의 조각으로 나눈다. 가상 페이지를 물리 페이지에 연결하면 물리적으로 흩어진 메모리도 프로그램에는 연속된 배열처럼 보인다. 페이지 테이블은 연결과 권한을 기록하고, [[운영체제 기본/보호#실행 권한, 주소, 자원의 경계|MMU]]는 이를 이용해 주소를 변환한다. 메모리를 읽을 때마다 운영체제를 호출하는 방식은 아니다.


페이지 폴트(page fault)는 메모리 접근을 하려는데 현재의 매핑이나 권한만으로 바로 처리할 수 없을 때 발생한다. 그 뒤의 결과는 원인에 따라 다르다. 유효한 매핑에 필요한 페이지를 준비하거나 copy-on-write를 처리한 뒤 실행을 계속할 수 있고, 잘못된 접근이면 프로세스에 신호가 전달될 수 있다. 따라서 페이지 폴트 횟수를 전부 프로그램 오류 횟수나 디스크 읽기 횟수로 해석해서는 안 된다.
예를 들어 페이지가 4 KiB라면 가상 주소 <code>0x1234</code>는 가상 페이지 번호 1과 페이지 내부 오프셋 <code>0x234</code>로 나뉜다. 페이지 1을 물리 페이지 9에 연결했다면 물리 주소는 <code>0x9234</code>가 된다. 변환되는 것은 페이지 번호이며, 페이지 안의 위치는 그대로 유지된다.


== 스왑은 가상 메모리의 전부가 아니다 ==
대신 변환 정보를 저장할 메모리와 이를 찾는 시간이 든다. CPU는 최근 변환 결과를 TLB(Translation Lookaside Buffer, 주소 변환 캐시)에 보관해 이 비용을 줄인다. 페이지를 크게 하면 같은 범위를 더 적은 항목으로 표현할 수 있지만, 일부만 쓰는 페이지의 낭비가 커지고 큰 물리 영역을 마련하기 어려워질 수 있다. 페이징은 연속된 물리 공간을 요구하는 부담을 줄이지만, 단편화와 관리 비용을 모두 없애지는 않는다. <ref name="source-1">[https://docs.kernel.org/admin-guide/mm/concepts.html 커널 문서: 주소 변환과 페이지 크기].</ref>
스왑은 메모리 관리에서 일부 데이터를 RAM 밖에 보관하는 데 사용하는 수단이다. 스왑을 사용하지 않더라도 가상 주소 공간, 메모리 보호, 공유 매핑은 사용한다.


또한 모든 페이지를 같은 방식으로 회수하지 않는다. 예를 들어 변경되지 않은 파일 기반 페이지는 버린 뒤 필요할 때 파일에서 다시 읽을 수 있다. 반면 파일에서 복구할 수 없는 데이터는 다른 처리가 필요하다. 메모리 부족을 이해하려면 단순한 사용량뿐 아니라 어떤 종류의 페이지가 차지하고 있는지도 봐야 한다.
== 필요한 순간에 메모리를 마련하기 ==
프로그램이 확보한 주소 범위를 항상 전부 사용하는 것은 아니다. 실행 파일에도 이번 실행에서는 읽지 않을 코드가 있고, 큰 배열에서도 일부만 접근할 수 있다. 처음부터 모든 내용을 RAM에 준비하는 대신 실제 접근할 때 페이지를 마련하면 사용하지 않는 부분의 비용을 피할 수 있다. 최근 사용한 데이터나 그 주변을 다시 사용하는 지역성이 높을수록 적은 RAM으로 많은 작업을 처리하기 유리하다.


== 주소가 아니라 매핑의 수명을 추적한다 ==
이 지연 할당을 가능하게 하는 것이 페이지 폴트다. 아직 준비하지 않은 페이지에 실제로 접근할 때 커널이 개입해 필요한 메모리를 마련한다.
가상 주소는 영구적인 물리 메모리의 이름이 아니다. 어느 프로세스의 어느 시점에 그 주소가 무엇과 연결되어 있는지가 중요하다. 주소 값이 같아도 프로세스가 다르면 다른 내용을 가리킬 수 있다. 한 프로세스에서도 매핑을 없앤 뒤 같은 주소에 새 매핑을 만들면 다른 대상을 가리킨다. 포인터의 숫자가 남았다고 접근할 권리까지 남는 것은 아니다.


파일 일부를 메모리에 매핑하면 파일 디스크립터와 매핑이라는 서로 다른 참조가 생긴다. Linux에서는 매핑을 만든 뒤 디스크립터를 닫아도 매핑은 유지된다. “파일을 닫는다”와 “그 내용을 메모리에서 더는 접근하지 않는다”는 같은 사건이 아니다.
이 설계는 초기 준비 비용과 메모리 사용량을 줄이는 대신 실제 접근 시점에 지연을 발생시킨다. 접근 시간이 일정해야 하는 작업에서는 이 변동 자체가 문제가 된다. 여러 작업이 반복해서 쓰는 페이지들의 집합이 RAM을 넘으면, 내보낸 페이지를 곧바로 다시 가져오는 일이 이어져 실제 계산보다 교체에 시간을 쓰게 된다. <ref name="source-2">[https://docs.freebsd.org/en/books/arch-handbook/vm/ FreeBSD Architecture Handbook: 가상 메모리].</ref>


사적 파일 매핑의 쓰기는 원래 파일이나 다른 매핑에 자신의 변경을 전달하지 않는다. 공유 파일 매핑은 다른 참여자에게 변경을 전달하는 경로가 되지만, 갱신 순서까지 정해 주지는 않는다. 자료구조를 함께 바꾸려면 동기화가 필요하다. 사적 매핑 역시 원본 파일의 이후 변경까지 차단한 고정 스냅샷을 뜻하지는 않는다.
== 페이지 폴트의 처리 ==
[[운영체제 기본/보호#보호 위반과 예외|보호]]에서 본 페이지 폴트는 CPU가 현재의 매핑과 권한으로 메모리 접근을 완료하지 못했다는 통지다. x86에서는 #PF 벡터로 [[운영체제 기본/장치 제어와 입출력#처리 진입점과 IDT|IDT에 등록된 커널 진입 코드]]를 실행한다. 이 시점에는 프로그램을 종료할지 아직 결정되지 않았다.


주소 공간의 논리적 독립성과 실제 물리 페이지의 공유도 양립할 수 있다. 따라서 “매핑된 범위는 얼마나 큰가”, “현재 물리 메모리에 얼마나 올라와 있는가”, “다른 프로세스와 공유하는 부분은 무엇인가”를 구분해야 한다. 이 질문들이 주소 공간, 상주 메모리, 공유 관계를 연결한다.
'''현재 페이지 테이블에 물리 페이지가 연결되어 있는가'''와 '''프로그램이 그 가상 주소를 사용할 수 있는가'''는 다른 질문이다. 운영체제는 주소 공간의 관리 정보에 허용된 범위와 접근 방식, 파일 같은 원본을 기록한다. 유효한 주소 범위를 먼저 제공하고 물리 페이지의 준비를 미뤄 두었다면, 페이지가 없다는 사실만으로 접근 위반이 되지는 않는다.<ref name="fault-handling">[https://docs.kernel.org/mm/page_tables.html Linux 커널 문서: Page Tables], Page Faults.</ref>


참고: [https://man7.org/linux/man-pages/man2/mmap.2.html mmap(2)], [https://man7.org/linux/man-pages/man2/fork.2.html fork(2)].
처리기는 문제가 된 주소와 읽기·쓰기 등의 접근 종류를 확인하고 다음과 같이 분기한다.


== /proc의 수치를 읽을 때 ==
# 허용되지 않은 주소이거나 해당 연산의 권한이 없다면 접근 위반으로 처리한다. 사용자 프로그램에 오류를 통지하며, 처리되지 않은 오류는 통상 프로세스 종료로 이어진다.
Bash에서 현재 셸의 정보를 읽어 보자.
# 허용된 영역인데 페이지를 아직 마련하지 않았다면 메모리를 할당하고 필요한 내용을 준비한다. 0으로 초기화된 메모리를 제공할 수도 있고 파일에서 읽어야 할 수도 있다.
# 논리적으로는 쓰기가 허용되지만 [[#공유하고, 필요할 때 복사하기|쓰기 시 복사]]를 위해 현재 페이지를 읽기 전용으로 공유 중이었다면, 필요에 따라 복사본을 마련하고 매핑을 바꾼다.
# 필요한 매핑과 권한을 갱신한 뒤, 폴트를 일으킨 명령을 다시 실행할 수 있는 상태로 복귀한다.<ref name="fault-handling" />


<pre>
<pre>
cat /proc/$$/status
메모리 접근 → 페이지 폴트 → 커널이 주소 공간의 규칙 확인
                            |
                            +→ 허용된 접근: 페이지 준비·매핑 갱신 → 명령 재실행
                            |
                            +→ 허용되지 않은 접근: 오류 통지 → 통상 종료
</pre>
</pre>


<code>VmSize</code>는 가상 메모리 크기이고, <code>VmRSS</code>는 RAM에 상주하는 메모리를 살펴보는 지표다. 가상 주소 공간에 잡힌 영역이 모두 RAM을 점유하는 것은 아니므로 두 값은 다를 수 있다.
필요한 데이터를 저장장치에서 가져와야 한다면 처리 중인 스레드가 입출력 완료를 기다릴 수 있다. 그동안 다른 스레드가 CPU를 사용하고, 완료 통지와 깨우기를 거쳐 실행이 재개된다. 이 부분은 [[운영체제 기본/장치 제어와 입출력#입출력 완료와 깨우기|입출력 완료와 깨우기]]로 연결된다. 모든 페이지 폴트가 디스크 읽기를 일으키는 것은 아니다.


<code>VmRSS</code>를 “이 프로세스만 독점하는 정확한 RAM 사용량”으로 해석하는 것도 틀리다. 공유 페이지가 포함될 수 있고 이 인터페이스의 계측 자체에도 정확도 제약이 있다. 여러 프로세스의 RSS를 단순히 더하면 공유 메모리를 중복해서 셀 수 있다. 비교할 때에는 먼저 측정값이 무엇을 세는지 확인해야 한다.
== 공유하고, 필요할 때 복사하기 ==
독립된 주소 공간도 같은 물리 페이지를 가리킬 수 있다. 변경하지 않는 코드나 데이터를 공유하면 중복 저장을 줄인다. 쓰기 가능한 공유 데이터는 복사를 줄이는 대신 참여자 사이의 동기화를 요구한다. 주소 변환은 접근 권한을 정할 뿐, 여러 실행 흐름의 갱신 순서를 정하지 않는다.
 
쓰기 시 복사(copy-on-write)는 처음에는 페이지를 공유하되 쓰기를 감지하도록 보호한다. 쓰기가 발생하면 필요한 페이지를 복사하고, 쓰는 쪽의 매핑을 복사본으로 바꾼다. 결국 변경하지 않을 데이터까지 미리 복사하는 비용을 피하지만, 첫 쓰기에 폴트와 복사가 발생하고 수정 범위가 넓으면 실제 메모리 사용도 늘어난다. 논리적인 독립성을 즉시 물리적 복사로 구현하지 않는 선택이다. <ref name="source-3">[https://man7.org/linux/man-pages/man2/fork.2.html Linux man-pages: fork(2)].</ref>
 
== 유한한 RAM과 매핑의 수명 ==
RAM이 부족하면 다시 읽을 수 있는 깨끗한 파일 페이지는 버릴 수 있다. 변경한 데이터는 보존할 곳이 필요하다. 파일에 반영하거나 스왑 같은 보조 저장소로 옮기는 데에는 입출력 시간이 든다. 스왑은 이 선택지 가운데 하나이며, 스왑이 없어도 주소 변환과 보호, 공유는 유효하다. 주소 공간을 크게 제공한다고 실제 데이터를 무제한으로 담거나 같은 속도로 접근할 수 있는 것은 아니다.
 
주소의 의미는 매핑이 유지되는 동안에만 성립한다. 매핑을 제거한 뒤 같은 주소를 재사용하면 남아 있는 포인터 값이 같아도 대상은 달라진다. 파일 매핑과 열린 파일의 참조도 수명이 다르다. Unix의 파일 매핑은 만들 때 사용한 디스크립터를 닫아도 유지될 수 있다. 사적 매핑의 변경은 원본 파일에 전달되지 않지만, 원본의 이후 변경까지 차단하는 고정 스냅샷을 보장하지는 않는다. 공유 여부, 접근 권한, 매핑의 수명은 각각 별도로 정해지는 조건이다. <ref name="source-4">[https://man7.org/linux/man-pages/man2/mmap.2.html Linux man-pages: mmap(2)].</ref>
== 관련 각론 ==
* [[운영체제 기본/Linux의 ELF 로딩/ELF 세그먼트와 주소 공간|ELF 세그먼트와 주소 공간]]: 실행 파일의 코드·데이터를 파일 매핑과 익명 메모리로 구성하는 과정.
* [[운영체제 기본/Linux의 파일 메모리 매핑|mmap을 통한 파일 읽기]]: 주소 영역 등록, 첫 메모리 접근, 파일 폴트와 PTE 설치.


== 참고 문헌 ==
== 참고 문헌 ==
* [https://docs.kernel.org/admin-guide/mm/concepts.html Linux 커널 문서: 메모리 관리 개념]
<references />
* [https://man7.org/linux/man-pages/man3/malloc.3.html malloc(3)]
* [https://man7.org/linux/man-pages/man2/mmap.2.html mmap(2)]
* [https://man7.org/linux/man-pages/man5/proc_pid_status.5.html proc_pid_status(5)]

2026년 10월 31일 (토) 09:26 기준 최신판

목차 · 이전: 동시성 · 다음: 파일과 입출력

프로그램은 배열과 포인터를 연속된 주소로 다루지만, 실제 RAM은 여러 프로그램이 나누어 쓰는 유한한 자원이다. 프로그램마다 필요한 크기도, 실행되는 시간도 다르다. 가상 메모리는 프로그램이 사용하는 주소와 실제 저장 위치 사이에 변환 계층을 두어 배치, 보호, 공유를 함께 다루는 설계다. 여기서는 주소 변환 하드웨어가 있는 시스템의 페이지 기반 방식을 설명한다.

배치의 자유와 보호를 함께 얻기

프로그램이 물리 주소를 직접 사용한다면 실행 위치가 바뀔 때 주소를 조정해야 한다. 한 프로그램의 배열이 커질 때 바로 뒤의 공간을 다른 프로그램이 차지하고 있을 수도 있다. 빈 공간의 총량이 충분해도 작은 조각으로 흩어져 있으면 큰 연속 영역을 배치하기 어렵다. 잘못 계산한 포인터가 다른 프로그램의 데이터를 덮어쓰는 문제도 별도로 막아야 한다.

가상 메모리는 각 프로세스에 독립적인 주소 공간을 제공한다. 같은 주소 값이라도 어느 주소 공간에서 사용되는지에 따라 다른 물리 메모리를 가리킨다. 프로그램은 자기 주소를 유지하고, 운영체제는 그 주소에 연결할 물리 메모리를 선택한다. 접근 권한도 이 연결에 포함하므로 읽기 전용 영역에 대한 쓰기나 허용되지 않은 주소의 접근을 하드웨어가 가려낼 수 있다. 배치의 자유를 얻는 동시에 프로그램 사이의 경계를 강제하는 것이다.

페이지 단위의 간접 참조와 그 비용

페이징은 가상 주소 공간과 물리 메모리를 일정한 크기의 조각으로 나눈다. 가상 페이지를 물리 페이지에 연결하면 물리적으로 흩어진 메모리도 프로그램에는 연속된 배열처럼 보인다. 페이지 테이블은 연결과 권한을 기록하고, MMU는 이를 이용해 주소를 변환한다. 메모리를 읽을 때마다 운영체제를 호출하는 방식은 아니다.

예를 들어 페이지가 4 KiB라면 가상 주소 0x1234는 가상 페이지 번호 1과 페이지 내부 오프셋 0x234로 나뉜다. 페이지 1을 물리 페이지 9에 연결했다면 물리 주소는 0x9234가 된다. 변환되는 것은 페이지 번호이며, 페이지 안의 위치는 그대로 유지된다.

대신 변환 정보를 저장할 메모리와 이를 찾는 시간이 든다. CPU는 최근 변환 결과를 TLB(Translation Lookaside Buffer, 주소 변환 캐시)에 보관해 이 비용을 줄인다. 페이지를 크게 하면 같은 범위를 더 적은 항목으로 표현할 수 있지만, 일부만 쓰는 페이지의 낭비가 커지고 큰 물리 영역을 마련하기 어려워질 수 있다. 페이징은 연속된 물리 공간을 요구하는 부담을 줄이지만, 단편화와 관리 비용을 모두 없애지는 않는다. [1]

필요한 순간에 메모리를 마련하기

프로그램이 확보한 주소 범위를 항상 전부 사용하는 것은 아니다. 실행 파일에도 이번 실행에서는 읽지 않을 코드가 있고, 큰 배열에서도 일부만 접근할 수 있다. 처음부터 모든 내용을 RAM에 준비하는 대신 실제 접근할 때 페이지를 마련하면 사용하지 않는 부분의 비용을 피할 수 있다. 최근 사용한 데이터나 그 주변을 다시 사용하는 지역성이 높을수록 적은 RAM으로 많은 작업을 처리하기 유리하다.

이 지연 할당을 가능하게 하는 것이 페이지 폴트다. 아직 준비하지 않은 페이지에 실제로 접근할 때 커널이 개입해 필요한 메모리를 마련한다.

이 설계는 초기 준비 비용과 메모리 사용량을 줄이는 대신 실제 접근 시점에 지연을 발생시킨다. 접근 시간이 일정해야 하는 작업에서는 이 변동 자체가 문제가 된다. 여러 작업이 반복해서 쓰는 페이지들의 집합이 RAM을 넘으면, 내보낸 페이지를 곧바로 다시 가져오는 일이 이어져 실제 계산보다 교체에 시간을 쓰게 된다. [2]

페이지 폴트의 처리

보호에서 본 페이지 폴트는 CPU가 현재의 매핑과 권한으로 메모리 접근을 완료하지 못했다는 통지다. x86에서는 #PF 벡터로 IDT에 등록된 커널 진입 코드를 실행한다. 이 시점에는 프로그램을 종료할지 아직 결정되지 않았다.

현재 페이지 테이블에 물리 페이지가 연결되어 있는가와 프로그램이 그 가상 주소를 사용할 수 있는가는 다른 질문이다. 운영체제는 주소 공간의 관리 정보에 허용된 범위와 접근 방식, 파일 같은 원본을 기록한다. 유효한 주소 범위를 먼저 제공하고 물리 페이지의 준비를 미뤄 두었다면, 페이지가 없다는 사실만으로 접근 위반이 되지는 않는다.[3]

처리기는 문제가 된 주소와 읽기·쓰기 등의 접근 종류를 확인하고 다음과 같이 분기한다.

  1. 허용되지 않은 주소이거나 해당 연산의 권한이 없다면 접근 위반으로 처리한다. 사용자 프로그램에 오류를 통지하며, 처리되지 않은 오류는 통상 프로세스 종료로 이어진다.
  2. 허용된 영역인데 페이지를 아직 마련하지 않았다면 메모리를 할당하고 필요한 내용을 준비한다. 0으로 초기화된 메모리를 제공할 수도 있고 파일에서 읽어야 할 수도 있다.
  3. 논리적으로는 쓰기가 허용되지만 쓰기 시 복사를 위해 현재 페이지를 읽기 전용으로 공유 중이었다면, 필요에 따라 복사본을 마련하고 매핑을 바꾼다.
  4. 필요한 매핑과 권한을 갱신한 뒤, 폴트를 일으킨 명령을 다시 실행할 수 있는 상태로 복귀한다.[3]
메모리 접근 → 페이지 폴트 → 커널이 주소 공간의 규칙 확인
                            |
                            +→ 허용된 접근: 페이지 준비·매핑 갱신 → 명령 재실행
                            |
                            +→ 허용되지 않은 접근: 오류 통지 → 통상 종료

필요한 데이터를 저장장치에서 가져와야 한다면 처리 중인 스레드가 입출력 완료를 기다릴 수 있다. 그동안 다른 스레드가 CPU를 사용하고, 완료 통지와 깨우기를 거쳐 실행이 재개된다. 이 부분은 입출력 완료와 깨우기로 연결된다. 모든 페이지 폴트가 디스크 읽기를 일으키는 것은 아니다.

공유하고, 필요할 때 복사하기

독립된 주소 공간도 같은 물리 페이지를 가리킬 수 있다. 변경하지 않는 코드나 데이터를 공유하면 중복 저장을 줄인다. 쓰기 가능한 공유 데이터는 복사를 줄이는 대신 참여자 사이의 동기화를 요구한다. 주소 변환은 접근 권한을 정할 뿐, 여러 실행 흐름의 갱신 순서를 정하지 않는다.

쓰기 시 복사(copy-on-write)는 처음에는 페이지를 공유하되 쓰기를 감지하도록 보호한다. 쓰기가 발생하면 필요한 페이지를 복사하고, 쓰는 쪽의 매핑을 복사본으로 바꾼다. 결국 변경하지 않을 데이터까지 미리 복사하는 비용을 피하지만, 첫 쓰기에 폴트와 복사가 발생하고 수정 범위가 넓으면 실제 메모리 사용도 늘어난다. 논리적인 독립성을 즉시 물리적 복사로 구현하지 않는 선택이다. [4]

유한한 RAM과 매핑의 수명

RAM이 부족하면 다시 읽을 수 있는 깨끗한 파일 페이지는 버릴 수 있다. 변경한 데이터는 보존할 곳이 필요하다. 파일에 반영하거나 스왑 같은 보조 저장소로 옮기는 데에는 입출력 시간이 든다. 스왑은 이 선택지 가운데 하나이며, 스왑이 없어도 주소 변환과 보호, 공유는 유효하다. 주소 공간을 크게 제공한다고 실제 데이터를 무제한으로 담거나 같은 속도로 접근할 수 있는 것은 아니다.

주소의 의미는 매핑이 유지되는 동안에만 성립한다. 매핑을 제거한 뒤 같은 주소를 재사용하면 남아 있는 포인터 값이 같아도 대상은 달라진다. 파일 매핑과 열린 파일의 참조도 수명이 다르다. Unix의 파일 매핑은 만들 때 사용한 디스크립터를 닫아도 유지될 수 있다. 사적 매핑의 변경은 원본 파일에 전달되지 않지만, 원본의 이후 변경까지 차단하는 고정 스냅샷을 보장하지는 않는다. 공유 여부, 접근 권한, 매핑의 수명은 각각 별도로 정해지는 조건이다. [5]

관련 각론

참고 문헌