1. 개요
- “CPU와 프로세스가 메모리 몇 번지에 무엇이 저장되어 있는지 모두 알고 있다?” ⇒ 그렇지 않음
- 위의 말처럼, 모든 정보를 다 알고 있기 위해서는 레지스터(CPU 내부 저장공간)가 메모리만큼 커야함 → 실제로는 훨씬 작은 용량만을 갖고 있음
- 메모리 정보는 시시각각 변할 수 있음
- 새로운 프로세스는 새롭게 메모리에 적재
- 사용되지 않는 프로세스는 메모리에서 삭제
- 이처럼, 실시간으로 변하는 정보를 모두 기억하고 있기는 어려움
- 그렇기 때문에, CPU는 메모리에 적재된 프로세스의 주소를 인식하고 관리하나?
→ ‘가상 메모리의 필요성’
2. 물리 주소와 논리 주소
- 물리 주소(Physical address): 하드웨어 상, 메모리의 실제 주소
- 논리 주소(Logical address): CPU와 프로세스가 이용하는 주소 체계, 프로세스마다 부여되는 0번지부터 시작하는 주소 체계
- 각각의 프로세스는 각각의 논리주소를 지님
- 각 프로세스의 논리주소의 번지수는 겹칠 수 있음
- 하드웨어 상의 메모리와 상호작용하기 위해서는, 반드시 논리 주소↔물리 주소 간 변환이 이루어져야 함
- 마치, 다른 언어로 소통하면 당연히 말이 안 통하는 사람처럼 (CPU는 논리 주소로 말하고, 메모리는 물리 주소로 말하고)
- MMU(Memory Management Unit, 메모리 관리 장치): 논리 주소↔물리 주소간 주소 변환을 위해 존재하는 하드웨어
- 메모리와 CPU 사이에 위치
- CPU가 이해하는 논리주소를 메모리가 이해하는 물리주소로 변환해줌

3. 스와핑과 연속 메모리 할당
- MMU를 기준으로 물리 주소와 논리 주소가 서로 변환됨 → 이를 통해 프로세스가 메모리 할당 수행
- 가장 기본적인 메모리 할당 방식: 스와핑 / 연속 메모리 할당
스와핑
- 메모리에 적재된 프로세스들 중, 현재 실행되지 않는 프로세스를 임시로 보조기억장치로 쫒아내는 작업
- 대상 프로세스: 대기 상태가 된 프로세스 / 오랫동안 사용하지 않는 프로세스 등
- 스왑 영역(swap space): 현재 실행되지 않는 프로세스들을 임시로 쫒아낸 보조기억장치 내의 영역명
- 스왑 아웃: 현재 실행되지 않는 프로세스가 메모리 → 스왑 영역으로 옮겨지는 것
- 스왑 인: 스왑 영역에 있는 프로세스 → 메모리로 옮겨오는 것
- 스왑 아웃 되었다가 스왑 인이 된다면, 스왑 아웃 이전의 물리 주소와는 다른 주소에 적재될 수 있음
- 스와핑(swapping): 프로세스를 쫒아내면, 메모리 상 빈 공간이 생김 → 이곳에 다른 프로세스를 적재하여 실행하는 메모리 관리 방식

연속 메모리 할당과 외부 단편화
- 연속 메모리 할당: 프로세스에 연속적인 메모리 공간을 할당하는 방식
- ex) 프로세스 A는 A의 크기만큼 메모리 주소를 할당 받아 배치 → 프로세스 B는 A 이후에 B의 크기만큼 연속적으로 배치

- ex) 프로세스 A는 A의 크기만큼 메모리 주소를 할당 받아 배치 → 프로세스 B는 A 이후에 B의 크기만큼 연속적으로 배치
- 외부 단편화 문제(external fragmentation)
- 연속 메모리 할당의 가장 큰 문제는 외부 단편화 문제를 내포하고 있다는 점
- ex) 아래 사진과 같이 메모리가 할당되어 있다고 가정
- 현재 이 메모리에 새로운 프로세스가 적재될 수 있는 빈 공간은 50MB
- 하지만 크기가 50MB인 프로세스를 아래 메모리에 적재할 수 없음 → 남은 공간이 20/30 각각 분리되어 남아있기 때문 → 메모리 낭비 초래

- 외부 단편화 문제가 발생하는 조건
- 프로세스들이 메모리에 연속적으로 할당되는 환경에서, 프로그램의 실행과 종료를 반복하며 메모리 사이 사이에 빈 공간이 생김
- 프로세스들이 메모리에 연속적으로 할당되는 환경에서, 프로그램의 실행과 종료를 반복하며 메모리 사이 사이에 빈 공간이 생김
4. 페이징을 통한 가상 메모리 관리
- 스와핑과 연속 메모리 할당의 두 가지 문제
- 외부 단편화 문제
- 물리 메모리보다 더 큰 프로세스는 실행 불가능
가상 메모리의 등장
- 위와 같이 스와핑과 연속 메모리 할당의 두가지 문제를 해결하기 위한 메모리 관리 기술이 바로 가상 메모리
- 가상 메모리(virtual memory)
- 실행하고자 하는 프로그램의 일부만 메모리에 적재 → 실제 메모리보다 더 큰 프로세스를 실행할 수 있도록
- 다양한 방식으로, 메모리를 실제 크기보다 더 크게 보이게 하는 기술
- 보조기억장치의 일부를 메모리처럼 활용
- 프로세스의 일부만 메모리에 적재
- 가상 주소 공간(virtual address space): 가상 메모리 기법으로 생성된 논리 주소 공간
- 가상 메모리 관리 기법의 종류
- 페이징 - 많은 운영체제에서 더 범용적으로 활용
- 세그멘테이션
페이징
- 페이징(paging)이란?
- 프로세스의 논리 주소 공간 → 페이지라는 일정한 단위로 나누고,
- 메모리의 물리 주소 공간 → 페이지와 동일한 크기의 프레임이라는 일정한 단위로 나눈 뒤,
- 페이지를 프레임에 할당함
- 페이지는 물리 메모리 내에 불연속적으로 할당 가능

- 페이지는 물리 메모리 내에 불연속적으로 할당 가능
- 페이징과 스와핑
- 페이징을 사용하는 시스템에서는, 프로세스 전체가 아닌 페이지 단위로 스왑 아웃/인 작업이 발생
- 페이징 시스템에서의 스왑 아웃/인: 페이지 아웃 / 페이지 인
세그멘테이션
- 프로세스를 일정한 크기의 페이지 단위가 아닌 가변적 크기의 세그먼트(segment) 단위로 분할 하는 방법
- 세그먼트는 일정한 단위로 분할되지는 않지만, 유의미한 논리적 단위로 분할

페이지 테이블
- 페이지 테이블?
- 프로세스를 구성하는 페이지는 물리 메모리 내 불연속적으로 배치될 수 있음
- 이럴 경우, CPU는 다음으로 실행할 페이지의 위치를 찾기가 어려움 (어떤 페이지가 어떤 프레임에 적재되었는지 모두 알고 있기는 어려움)
- 이를 해결하기 위해 ‘페이지- 적재된 프레임’을 짝지어주는 페이지 테이블 활용
- 페이지 테이블에는 페이지 번호와 실재 적재된 프레임 번호가 대응되어 있음

- 프로세스를 구성하는 페이지는 물리 메모리 내 불연속적으로 배치될 수 있음
- 페이지 테이블의 구성요소
- 페이지 테이블 엔트리(PTE, Page Table Entry): 페이지 테이블을 구성하는 각각의 행
- 페이지 테이블 엔트리에 담기는 정보의 종류
- 가장 중요: ‘페이지 번호 - 실재 적재된 프레임 번호’ 대응 데이터
- 그 외 대표적 정보: 프레임 번호, 유효 비트, 보호 비트, 참조 비트, 수정 비트 등
- 유효 비트(valid bit): 해당 페이지에 접근이 가능한지 여부를 담은 정보(중요)
- 현재 페이지가 보조기억장치에 저장되어 있는지, 메모리에 저장되어 있는지
- 페이지가 메모리에 적재되어 있다면 1, 그렇지 않다면 0으로 표기
- 페이지 폴트(page fault)
- 메모리에 적재되지 않은 페이지(=유효 비트가 0인 페이지)에 접근하려 할 때 발생하는 예외(Exception)
- 보호 비트(protection bit)
- 페이지 보호 기능을 위해 존재하는 비트
- 읽기: r / 쓰기: w / 실행: x 의 조합으로 페이지 접근 권한 제한하여 보호
- 참조 비트(reference bit)
- CPU가 해당 페이지에 접근한 적이 있는지 여부를 나타낸 비트
- 페이지 적재 이후,
- CPU가 읽거나 쓴 페이지: 1
- CPU가 한 번도 읽거나 쓰지 않은 페이지: 0
- 수정 비트(modified bit, 더티 비트)
- 해당 페이지에 데이터를 쓴 적이 있는지 여부를 나타낸 비트
- 수정 비트가 1: 변경된 적이 있는 페이지
- 페이지를 메모리에서 삭제해야 할 때, 페이지의 수정내역을 보조기억장치에도 반영해 두어야 함 → 보조 기억 장치에 대한 쓰기 작업 필요
- 수정 비트가 0: 변경된 적이 없는 페이지
- 이 경우에는 보조기억장치에 반영할 수정 내역이 없음 → 쓰기 작업 없이 페이지를 메모리에서 삭제만 하면 됨

- 이 경우에는 보조기억장치에 반영할 수정 내역이 없음 → 쓰기 작업 없이 페이지를 메모리에서 삭제만 하면 됨
- 수정 비트가 1: 변경된 적이 있는 페이지
- 해당 페이지에 데이터를 쓴 적이 있는지 여부를 나타낸 비트
- 유효 비트(valid bit): 해당 페이지에 접근이 가능한지 여부를 담은 정보(중요)
내부 단편화
- 페이징을 통해 외부 단편화 문제를 해결할 수 있지만, 이의 반대급부로 내부 단편화라는 또 다른 문제를 야기할 수 있음
- 내부 단편화?
- 모든 프로세스가 페이지의 크기로 딱 맞게 잘리지 않음 (=모든 프로세스의 크기가 페이지 크기의 배수가 아님)
- 이러한 현상으로 인해 발생하게 되는 메모리 낭비: 내부 단편화(internal fragmentation)

페이지 테이블 베이스 레지스터(PTBR)
- 프로세스 실행을 위해서는 해당 프로세스의 테이블 메모리가 적재된 위치를 알아야 함 → 이를 가리기는 특별한 레지스터: PTBR(Page Table Base Register)
- PTBR은 프로세스 마다 갖는 정보 → 각 PCB에 기록, 다른 프로세스로 문맥 교환 시 변경

- 운영체제에서, PTBR은 가급적 메모리에 적재하는 것을 지양함
- 이유 1: 메모리 접근 횟수가 많아짐
- 모든 프로세스의 PTBR이 메모리에 적재되어 있다면, 실제 프레임에 접근하기 위해서는 한 프레임 당 두 번씩 메모리에 접근해야됨
- 페이지 테이블에 접근하기 위해 한 번
- 실제 프레임에 접근하기 위해 한 번 → 메모리에 접근하는 시간이 두 배로 불어남
- 해결책: TLB(Translation Look-aside Buffer) → “페이지 테이블의 캐시 메모리”
- ‘참조 지역성의 원리’에 근거해 자주 사용할 법한 페이지 위주로 페이지 테이블의 일부 내용 저장
- TLB 히트: CPU가 접근하려는 논리 주소의 페이지 번호가 TLB에 있는 경우, TLB가 CPU에 해당 페이지 번호를 알려주는 것 → 이 경우에는 한 번만 메모리에 접근하면 됨
- TLB 미스: 페이지 번호가 TLB에 없는 경우, 페이지에 적재된 프레임을 알아내기 위해 메모리 내의 페이지 테이블에 접근하는 수밖에 없음 → 추가적인 메모리 접근 필요
⇒ 메모리 접근 횟수를 낮추려면 TLB 히트율을 높여야 함

- 모든 프로세스의 PTBR이 메모리에 적재되어 있다면, 실제 프레임에 접근하기 위해서는 한 프레임 당 두 번씩 메모리에 접근해야됨
- 이유 2: 메모리 용량 비효율
- 프로세스 크기가 커지면 자연스레 페이지 테이블의 크기도 커짐 → 모든 페이지 테이블 엔트리를 그대로 메모리에 두는 것은 매우 비효율적인 메모리 관리
- 해결책: 계층적 페이징(Hierarchical paging)
- 간단하게 말하면, 페이지 테이블을 페이징하는 방식
- 여러 단계의 페이지를 둠 → “다단계 페이지 테이블 기법”
- 과정(아래 사진 예시)
- 우선, 프로세스의 페이지 테이블을 여러 개의 페이지로 자름
- 이후, CPU와 가까이 위치한 바깥 쪽에 페이지 테이블(Outer 페이지 테이블)을 하나 더 두어 잘린 페이지 테이블들을 가리키게 함
- 이렇게 구성하게 되면, Outer 메모리 테이블만 메모리에 유지하여 언제든 페이지 테이블에 접근 가능해짐
- 잘린 테이블의 일부가 보조기억장치에 있어도, Outer 페이지 테이블을 통해 언제든 접근 가능

- 잘린 테이블의 일부가 보조기억장치에 있어도, Outer 페이지 테이블을 통해 언제든 접근 가능
- 이유 1: 메모리 접근 횟수가 많아짐
페이징 주소 체계
- 하나의 페이지에는 여러 주소가 포함
- 페이징 시스템의 논리 주소: <페이지 번호, 변위>
- 페이지 번호(page number): “몇 번째 페이지에 접근할지”
- 변위(offset): 접근하는 주소가 페이지(프레임)에서 얼마나 떨어져 있나

- 페이지 테이블을 통해, 논리주소 "페이지 번호, 변위" → 물리주소"프레임 번호, 변위"로 변환
- ex) 하나의 페이지 및 프레임이 4개의 주소로 구성되어 있는, 아래와 같은 상황 가정
- CPU가 <5, 2>라는 논리 주소에 접근한다면?(5번 페이지, 변위 2)
- 현재 5번 페이지는 1번 프레임에 있음(페이지 테이블 정보)
- CPU는 이에 따라 1번 프레임, 변위 2에 접근
- 1번 프레임은 물리 주소 공간 상에서는 8번지에서 시작하므로
- CPU는 8번지에서 변위 2를 더한 10번지에 접근

- CPU가 <5, 2>라는 논리 주소에 접근한다면?(5번 페이지, 변위 2)
5. 페이지 교체 알고리즘
- 요구 페이징(Demand Paging): 처음부터 모든 페이지를 적재하지 않고, 메모리에 필요한 페이지만을 적재하는 기법
- 발생 양상
- CPU가 특정 페이지에 접근하는 명령어 실행
- 유효 비트가 1일 경우
- CPU는 페이지가 적재된 프레임에 접근
- 유효 비트가 0인 경우
- 페이지 폴트 발생 → 페이지 폴트 루틴을 통해 해당 페이지를 메모리로 적재 → 유효 비트 1로 설정
- 과정 반복
- 페이지 폴트의 종류 - 크게 아래와 같이 구분
- 메이지 페이지 폴트
- 입출력 작업이 필요한 페이지 폴트
- CPU가 접근하고자 하는 페이지가 물리 메모리에 없을 경우 발생
- 마이너 페이지 폴트
- 입출력 작업이 불필요한 페이지 폴트
- CPU가 접근하고자 하는 페이지가 물리 메모리에 존재하지만, 페이지 테이블 상에 반영되지 않은 경우 발생 → 일반적으로 성능 상 악영향이 메이저 페이지 폴트에 비해 덜함
- 순수 요구 페이징(pure demand paging): 아무 페이지도 메모리에 적재하지 않고 무작정 프로세스를 실행하는 것
- 이 경우, 첫 명령어를 실행한 순간부터 페이지 폴트 발생
- 이 경우, 첫 명령어를 실행한 순간부터 페이지 폴트 발생
- 페이지 교체 알고리즘(Page replacement algorithm)
- 여러 번의 요구 페이징을 거치며 수많은 페이지들이 메모리에 적재될 것임 → 언젠가는 메모리가 가득찬다면, 일부 페이지를 스왑 아웃 해야함
- 여기서, 스왑 아웃 해낼 페이지를 선택하는 방법이 페이지 교체 알고리즘
- 페이지 교체 알고리즘은, 곧 컴퓨터 전체 성능과 직결됨 → 페이지 폴트의 발생 빈도를 결정해주기 때문
- 지나친 페이지 교체를 유발하는 알고리즘은 컴퓨터 성능 하락의 요인임 → “스래싱(thrashing) 문제 발생”
- 페이지 교체 알고리즘의 종류
- FIFO 페이지 교체 알고리즘
- 선입선출, 메모리에 가장 먼저 적재된 페이지부터 스왑 아웃하는 알고리즘
- 간편 및 간단한 구현
- 초기부터 줄곧 참조하고 있는 페이지를 스왑 아웃 시킬 우려
- 최적 페이지 교체 알고리즘
- 앞으로의 사용 빈도가 가장 낮은 페이지를 교체하는 알고리즘 → “낮은 페이지 폴트율” 보장을 위한 알고리즘
- “앞으로 가장 적게 사용할 페이지” 예측이 어렵기에, 실제 구현이 어려움
- LRU 페이지 교체 알고리즘
- 그간 가장 적게 사용한 페이지를 교체하는 알고리즘
- 보편적으로 활용, 이를 기반으로 한 다양한 파생 알고리즘 존재
- FIFO 페이지 교체 알고리즘
chat_bubble 댓글남기기
댓글남기기