본문으로 이동
주 메뉴
주 메뉴
사이드바로 이동
숨기기
둘러보기
대문
최근 바뀜
임의 문서로
~ldmsys
검색
검색
외관
로그인
개인 도구
로그인
현재 모든 문서는 작성 중입니다. 보시는 데 불편함이 있더라도 양해 부탁드립니다.
운영체제 기본/가상 메모리 문서 원본 보기
문서
토론
한국어
읽기
원본 보기
역사 보기
도구
도구
사이드바로 이동
숨기기
작업
읽기
원본 보기
역사 보기
일반
여기를 가리키는 문서
가리키는 글의 최근 바뀜
문서 정보
외관
사이드바로 이동
숨기기
←
운영체제 기본/가상 메모리
문서 편집 작업을 수행할 권한이 없습니다. 다음 이유를 확인해주세요:
요청한 작업은 다음 권한을 가진 사용자에게 제한됩니다:
사용자
.
문서의 원본을 보거나 복사할 수 있습니다.
[[운영체제 기본|목차]] · 이전: [[운영체제 기본/동시성|동시성]] · 다음: [[운영체제 기본/파일과 입출력|파일과 입출력]] 프로그램은 배열과 포인터를 연속된 주소로 다루지만, 실제 RAM은 여러 프로그램이 나누어 쓰는 유한한 자원이다. 프로그램마다 필요한 크기도, 실행되는 시간도 다르다. 가상 메모리는 프로그램이 사용하는 주소와 실제 저장 위치 사이에 변환 계층을 두어 배치, 보호, 공유를 함께 다루는 설계다. 여기서는 주소 변환 하드웨어가 있는 시스템의 페이지 기반 방식을 설명한다. == 배치의 자유와 보호를 함께 얻기 == 프로그램이 물리 주소를 직접 사용한다면 실행 위치가 바뀔 때 주소를 조정해야 한다. 한 프로그램의 배열이 커질 때 바로 뒤의 공간을 다른 프로그램이 차지하고 있을 수도 있다. 빈 공간의 총량이 충분해도 작은 조각으로 흩어져 있으면 큰 연속 영역을 배치하기 어렵다. 잘못 계산한 포인터가 다른 프로그램의 데이터를 덮어쓰는 문제도 별도로 막아야 한다. 가상 메모리는 각 프로세스에 독립적인 주소 공간을 제공한다. 같은 주소 값이라도 어느 주소 공간에서 사용되는지에 따라 다른 물리 메모리를 가리킨다. 프로그램은 자기 주소를 유지하고, 운영체제는 그 주소에 연결할 물리 메모리를 선택한다. 접근 권한도 이 연결에 포함하므로 읽기 전용 영역에 대한 쓰기나 허용되지 않은 주소의 접근을 하드웨어가 가려낼 수 있다. 배치의 자유를 얻는 동시에 프로그램 사이의 경계를 강제하는 것이다. == 페이지 단위의 간접 참조와 그 비용 == 페이징은 가상 주소 공간과 물리 메모리를 일정한 크기의 조각으로 나눈다. 가상 페이지를 물리 페이지에 연결하면 물리적으로 흩어진 메모리도 프로그램에는 연속된 배열처럼 보인다. 페이지 테이블은 연결과 권한을 기록하고, [[운영체제 기본/보호#실행 권한, 주소, 자원의 경계|MMU]]는 이를 이용해 주소를 변환한다. 메모리를 읽을 때마다 운영체제를 호출하는 방식은 아니다. 대신 변환 정보를 저장할 메모리와 이를 찾는 시간이 든다. CPU는 최근 변환 결과를 TLB(Translation Lookaside Buffer, 주소 변환 캐시)에 보관해 이 비용을 줄인다. 페이지를 크게 하면 같은 범위를 더 적은 항목으로 표현할 수 있지만, 일부만 쓰는 페이지의 낭비가 커지고 큰 물리 영역을 마련하기 어려워질 수 있다. 페이징은 연속된 물리 공간을 요구하는 부담을 줄이지만, 단편화와 관리 비용을 모두 없애지는 않는다. <ref name="source-1">[https://docs.kernel.org/admin-guide/mm/concepts.html 커널 문서: 주소 변환과 페이지 크기].</ref> == 필요한 순간에 메모리를 마련하기 == 프로그램이 확보한 주소 범위를 항상 전부 사용하는 것은 아니다. 실행 파일에도 이번 실행에서는 읽지 않을 코드가 있고, 큰 배열에서도 일부만 접근할 수 있다. 처음부터 모든 내용을 RAM에 준비하는 대신 실제 접근할 때 페이지를 마련하면 사용하지 않는 부분의 비용을 피할 수 있다. 최근 사용한 데이터나 그 주변을 다시 사용하는 지역성이 높을수록 적은 RAM으로 많은 작업을 처리하기 유리하다. 이 지연 할당을 가능하게 하는 것이 페이지 폴트다. 아직 준비하지 않은 페이지에 실제로 접근할 때 커널이 개입해 필요한 메모리를 마련한다. 이 설계는 초기 준비 비용과 메모리 사용량을 줄이는 대신 실제 접근 시점에 지연을 발생시킨다. 접근 시간이 일정해야 하는 작업에서는 이 변동 자체가 문제가 된다. 여러 작업이 반복해서 쓰는 페이지들의 집합이 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> 처리기는 문제가 된 주소와 읽기·쓰기 등의 접근 종류를 확인하고 다음과 같이 분기한다. # 허용되지 않은 주소이거나 해당 연산의 권한이 없다면 접근 위반으로 처리한다. 사용자 프로그램에 오류를 통지하며, 처리되지 않은 오류는 통상 프로세스 종료로 이어진다. # 허용된 영역인데 페이지를 아직 마련하지 않았다면 메모리를 할당하고 필요한 내용을 준비한다. 0으로 초기화된 메모리를 제공할 수도 있고 파일에서 읽어야 할 수도 있다. # 논리적으로는 쓰기가 허용되지만 [[#공유하고, 필요할 때 복사하기|쓰기 시 복사]]를 위해 현재 페이지를 읽기 전용으로 공유 중이었다면, 필요에 따라 복사본을 마련하고 매핑을 바꾼다. # 필요한 매핑과 권한을 갱신한 뒤, 폴트를 일으킨 명령을 다시 실행할 수 있는 상태로 복귀한다.<ref name="fault-handling" /> <pre> 메모리 접근 → 페이지 폴트 → 커널이 주소 공간의 규칙 확인 | +→ 허용된 접근: 페이지 준비·매핑 갱신 → 명령 재실행 | +→ 허용되지 않은 접근: 오류 통지 → 통상 종료 </pre> 필요한 데이터를 저장장치에서 가져와야 한다면 처리 중인 스레드가 입출력 완료를 기다릴 수 있다. 그동안 다른 스레드가 CPU를 사용하고, 완료 통지와 깨우기를 거쳐 실행이 재개된다. 이 부분은 [[운영체제 기본/장치 제어와 입출력#입출력 완료와 깨우기|입출력 완료와 깨우기]]로 연결된다. 모든 페이지 폴트가 디스크 읽기를 일으키는 것은 아니다. == 공유하고, 필요할 때 복사하기 == 독립된 주소 공간도 같은 물리 페이지를 가리킬 수 있다. 변경하지 않는 코드나 데이터를 공유하면 중복 저장을 줄인다. 쓰기 가능한 공유 데이터는 복사를 줄이는 대신 참여자 사이의 동기화를 요구한다. 주소 변환은 접근 권한을 정할 뿐, 여러 실행 흐름의 갱신 순서를 정하지 않는다. 쓰기 시 복사(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> == 참고 문헌 == <references />
운영체제 기본/가상 메모리
문서로 돌아갑니다.
검색
검색
운영체제 기본/가상 메모리 문서 원본 보기
새 주제