본문 바로가기
TIL (Today I Learned)/컴퓨터 시스템(CS)

[CS] CS:APP #9

by 둥굴프 2022. 12. 6.
해당 포스트는 다음 서적을 참고하여 작성하였습니다. [컴퓨터 시스템(CS:APP) 제 3판, 퍼스트북]

 

이번 포스팅에서는 CS:APP의 챕터 9, 가상메모리에 대해서 다루겠다.

가상메모리에 대해서 이해하기 위해서는 다음의 키워드를 선수학습 하길 권장한다.

프로세스, 캐시메모리와 캐시 미스, 메모리 관리

 

다음 그림은 Process Model에 대한 그림이다.

여러개의 프로세스가 동작하는 원리를 알면 가상 메모리의 동작환경을 이해하는 데 큰 도움이 된다.

프로세스가 어떻게 동작하는지 알면 좋다.

 

CHAPTER 9

 

여러 프로세스들이 하나의 메인 메모리를 공유하는 것은 특별한 어려움을 만나게 한다.

CPU에 대한 요구가 증가함에 따라 프로세스들은 점점 느려진다.

또한 다양한 에러를 야기한다.

 

메모리를 보다 효율적이고 더 적은 에러를 갖도록 관리하기 위해서 현대의 시스템은 가상메모리virtual memory VM라고 알려진 메인 메모리의 추상화를 제공한다. 가상메모리는 각 프로세스에 하나의 크고 통합된, 사적 주소공간을 제공한다.

 

가상 메모리는 세 개의 중요한 기능을 제공한다.

(1) 메인 메모리를 디스크에 저장된 주소공간에 대한 캐시로 취급한다.

(2) 각 프로세스에 통일된 주소공간을 제공함으로써 메모리 관리를 단순화한다.

(3) 각 프로세스의 주소공간을 다른 프로세스에 의한 송상으로부터 보호한다.

 

 

9.1 물리 및 가상주소 방식

 

물리 주소(PA) 방식 : CPU가 메모리에 접근하는 가장 자연스러운 방식

주소 번역 : 가상주소를 물리 주소로 변환하는 작업

메모리 관리 유닛(MMU) : CPU칩 내에 있는 하드웨어.

메인 메모리에 저장된 참조 테이블을 사용해서 실행 중에 가상주소를 번역하며, 이 테이블의 내용은 운영체제가 관리한다.

 

9.2 주소공간

 

선형 주소공간 : 주소공간의 정수가 연속적

CPU는 가상 주소공간이라고 불리는 N = 2^n 주소의 주소공간에서 가상의 주소를 생성한다.

32비트 운영체제의 가상 주소공간 = 2^32 ( 32비트 주소공간이라고 부른다 )

컴퓨터 시스템은 시스템 내의 M바이트로 대응되는 물리 주소 공간을 갖는다.

논의를 단순하게 하기 위해서 M=2^m이라고 가정한다.

주소공간의 개념은 데이터 객체와 그들의 특성(주소)들 간에 명확한 구별을 해준다.

메인 메모리의 각 바이트는 가상 주소공간으로부터 선택된 가상주소를 가진다.

 

9.3 캐싱 도구로서의 VM

 

VM system : 가상메모리를 규정된 사이즈 블록 단위로 분할하여 관리한다.

가상 페이지 : 분할된 블록

 

가상페이지의 집합은 세 개의 중첩되지 않는 부분집합으로 나누어진다.

(1) Unallocated : VM시스템에 의해 아직까지 할당되지 않은 페이지들, 디스크 상에 어떤 공간도 차지하지 않는다.

(2) Cashed : 현재 물리 메모리에 캐시되어 할당된 페이지들.

(3) Uncashed : 물리 메모리에 캐시되지 않은 할당된 페이지들.

 

9.3.1 DRAM 캐시의 구성

 

SRAM 캐시 : CPU와 메인 메모리 사이의 L1, L2, L3

DRAM 캐시 : 가상페이지를 메인 메모리로 캐싱하는 VM 시스템 캐시

 

큰 규모의 캐시 미스 비용과 첫 번재 바이트를 접근하는 데 드는 비용 때문에 가상 페이지는 4KB에서 2MB까지 값을 가진다.

 

9.3.2 페이지 테이블

 

페이지 테이블 : 가상페이지를 물리페이지로 매핑하는 자료구조의 조합. (물리 메모리에 저장되어있다.)

운영체제는 페이지 테이블의 콘텐츠 관리와 페이지들을 디스그와 DRAM 사이에서 왔다 갔다 하는 것을 관장한다.

페이지 테이블은 페이지 테이블 엔트리(PTE)의 배열이다.

 

필요 페이지 테이블 엔트리 구하는 방법 :

(1) 가상주소크기(n)와 페이지 크기(P)가 주어졌음을 가정한다.

(2) 가상주소크기에 맞는 가상 메모리 크기는 다음과 같다.

가상 메모리 용량 = 2^n

(3) 가상 메모리 크기를 페이지 크기로 나누면 필요한 페이지 개수를 구할 수 있다.

PTE 개수 ( 페이지 개수 ) = 2^n / P

 

9.3.4 페이지 오류

 

페이지 오류page fault : DRAM 캐시 미스

(1) CPU가 Uncashed상태의 페이지를 읽으면 페이지 오류 예외를 유발시킨다.

(2) 커널 내의 페이지 오류 예외 핸들러를 호출한다.

(3) 커널은 희생가 페이지를 선택한다.

(만약 희생자 페이지의 데이터가 변경되었다면 이를 복사하여 디스크에 반영)

(4) 희생자 페이지의 상태를 Uncashed로 수정한다.

(해당하는 페이지 테이블 엔트리를 수정)

(5) 읽고자 하는 페이지를 메인 메모리에 캐싱한다.

(해당하는 페이지 테이블 엔트리를 수정)

(6) 오류 인스트럭션을 재시작한다.

 

페이지 : 블록

스와핑swapping 또는 페이징 : 디스크와 메모리 사이에 페이지를 전송하는 동작

요구 페이징demand paging : 미스가 발생할 때, 하나의 페이지로 스와핑되어 들어오는 마지막 순간까지 기다리는 전략

프로세스가 처음 실행되면 Demand paging에 의해 Page fault가 자주 발생할 수 밖에 없다.
어느 수준까지 실행된 이후에는 Page fault가 줄어든다.

 

9.3.6 문제해결을 위한 또 한 번의 지역성의 등장

 

큰 미스 비용을 생각하면 페이징이 프로그램 성능을 파괴할 것이라고 예상한다.

그러나 지역성의 문제로 가상 메모리는 잘 동작한다.

출처 : Abraham Silberschatz, Greg Gagne, and Peter Baer Galvin, "Operating System Concepts, Ninth Edition

 

지역성의 원리는 시간상의 어느 시점에서라도 이들이 동작 집합working set 또는 거주 집합resident set이라고 알려진 보다 작은 활성화된 페이지 집합에서 동작하는 경향을 보일 것이라는 점을 약속한다.

 

만일, 동작 집합 크기가 물리 메모리보다 크면, 프로그램을 쓰래싱thrashing을 일으킨다.

thrashing : page fault가 계속해서 일어나는 현상

 

9.4 메모리 관리를 위한 도구로서의 VM

 

운영체제는 각 프로세스마다 별도의 페이지 테이블을 제공한다.

즉, 별도의 가상 주소공간을 제공한다.

 

9.6.1 캐시와 VM의 통합

 

SRAM 캐시를 접근하기 위해서 대부분의 시스템이 물리 주소를 사용한다.

가상페이지로부터 블록을 공유하는 것이 단순해진다.

주소 번역과정의 일부로 접근 권한이 체크되된다.

( 캐시가 보호 이슈를 다룰 필요가 없다. )

페이지 테이블 엔트리들이 다른 테이터 워드와 마찬가지로 캐싱될 수 있다.

 

9.6.2 TLB를 사용한 주소 번역 속도의 개선

 

CPU가 가상주소를 생성할 때마다 MMU는 가상주소를 물리 주소로 번역하기 위해서 PTE를 참조해야 한다.

이 과정에서 발생하는 비용을 줄이기 L1을 사용한다.

이 비용마저도 제거하기 위해 TLB라고 부르는 작은 캐시를 사용한다.

번역 참조 버퍼 TLB translation looaside buffer : 작은 가상주소지정 캐시.

( 각 라인은 하나의 PTE로 구성된 하나의 블록을 저장 )

 

9.6.3 다중 레벨 페이지 테이블

 

32비트 주소공간, 4KB 페이지, 4바이트 PTE의 경우 항상 4MB의 페이지 테이블을 필요로 하게 된다.

32비트 주소공간의 크기 = 2^32 byte = 4GB

페이지의 주소공간의 크기 = 4KB

4GB / 4KB = 1M개의 엔트리 필요.

4Byte * 1M = 4MB의 페이지 테이블 크기 요구된다.

 

이를 해결하기 위해 다중 레벨 페이지 테이블 활용.

1. 만일 1단계 테이블의 PTE가 NULL이면, 해당 2단계 페이지 테이블이 존재할 필요가 없어진다.

2. 1단계 테이블만이 항상 메인 메모리에 있을 필요가 있다.

2단계 페이지 테이블은 이들이 필요할 때 VM 시스템에 의해서 생성되고, 페이지 인 또는 아웃될 수 있으며, 이로 인해 메인 메모리로부터의 압박을 줄일 수 있다.

단일 페이지 테이블과 다중 레벨 페이지 테이블 비교

1단계 테이블 : 2^20 * 2^12(1페이지의 주소크기 = 4KB)

2단계 테이블 : 2^10 * 2^10 * 2^12(1페이지의 주소크기 = 4KB)

 

9.7 사례 연구 : 인텔 코어 i7/리눅스 메모리 시스템

 

리눅스는 4 KB 페이지 크기를 사용한다.

 

9.7.1 코어 i7에서의 주소 번역

 

코어 i7은 4단 페이지 테이블 계층구조를 사용한다.

각 프로세스는 자신만의 사적인 페이지 테이블 계층구조를 갖는다.

CR3 제어 레지스터는 1단 페이지 테이블(L1)의 시작 부분의 물리 주소를 가지고 있다.

CR3의 값은 각 프로세스 컨텍스트의 일부분이며 각 문맥 전환 동안에 복원된다.

 

9.7.2 리눅스 가상메모리 시스템

 

각 프로세스에 대해 별도의 가상 주소공간을 유지한다.

커널 가상메모리는 커널 내의 코드와 데이터 구조를 포함한다.

일부 커널 가상메모리 영역은 모든 프로세스가 공유하는 물리페이지에 매핑되어 있다.

 

리눅스 가상메모리 영역

영역이라는 개념은 중요한데, 이것이 가상 주소공간이 간격을 가질 수 있도록 해주기 때문이다.

커널은 시스템 내 각 프로세스를 위해 고유의 태스크 구조를 관리한다(task_struct).

태스크 구조의 원소들은 커널이 프로세스를 실행하는 데 필요한 모든 정보를 포함하거나 가리킨다.

(예 : PID, 사용자 스택으로의 포인터, 실행 가능 목적파일의 이름, 프로그램 카운터)

 

9.8 메모리 매핑

malloc으로 메모리를 동적할당 하면 path가 존재하지 않는 heap memory에 할당된다.

이것은 anonymous memory가 된다.

왜냐하면 디스크에 힙 메모리의 사본파일이 존재하지 않기 때문이다.

이 이유 때문에 무기명 파일로 매핑된 영역 내의 페이지들은 무요구 demand-zero 페이지라고 불린다.

 

9.8.1 다시 보는 공유 객체

오류 핸들러가 어떤 페이지를 사적 copy-on-write 영역에 쓰려고 하는 프로세스에 의해서 보호 예외가 발생했다고 알릴 때.

(1) 페이지의 새로운 사본을 물리페이지에 만든다.

(2) 페이지 테이블을 갱신해서 새로운 사본을 가리키도록 한다.

(3) 페이지에 대한 쓰기 허가를 복원한다.

 

copy-on-write는 마지막 가능한 순간까지 사적 객체 내에서 페이지를 복사하는 것을 지연시켜서 부족한 물리 메모리를 가장 효율적으로 사용한다.

 

 9.9 동적 메모리 할당

동적 메모리 할당기 : 힙heap이라고 하는 프로세스의 가상메모리 영역을 관리

할당기는 힙을 다양한 크기의 블록들의 집합으로 관리한다.

가용 블록 : 명시적으로 할당할 때까지 가용한 상태로 남아 있다.

할당된 블록 : 명시적으로 또는 메모리 할당기 자신에 의해 묵시적으로 반환될 때까지 할당된 채로 남아 있다.

 

명시적 할당기 : 명시적으로 할당된 블록을 반환해 줄 것을 요구한다.

C표준 라이브러리의 malloc 패키지 블록 할당, free 블록 반환

C++ new, delete

 

묵시적 할당기 : 할당기가 블록을 언제 반환하는지 검출한다.

가비지 컬렉터garbage collector, 자동으로 사용하지 않은 할당된 블록을 반환시켜주는 작업을 가비지 컬렉션이라고 부른다.

 

9.9.2 왜 동적 메모리 할당인가?

 

런타임에 동적으로 할당

배열의 최대 크기는 가용한 가상메모리의 양에 의해서만 제한된다.

 

9.9.3 할당기 요구사항과 목표

 

명시적 할당기의 제한사항

1.임의의 요청 순서 처리하기 : 할당기는 모든 할당 요청이 대응되는 요청이 함께 존재한다거나 쌍을 이루는 할당과 반환 free 요청이 연속된다는 가정을 할 수 없다.

2. 요청에 즉시 응답하기 : 할당기는 할당/반환 요청이 들어왔을 때, 즉시 그 요청을 시행해야한다.

3. 힙만 사용하기 : 확장성을 갖기 위해서 할당기가 사용하는 비확장성 자료 구조들은 힙 자체에 저장되어야 한다.

4. 블록 정렬하기(정렬 요건) : 할당기는 어떤 종류의 데이터 객체라도 저장할 수 있도록 하는 방식으로 정렬해야 한다.

5. 할당된 블록을 수정하지 않기 : 일단 블록이 할당되면 이들을 수정하거나 이동하지 않는다. 할당된 블록들을 압축하는 것 같은 기법들은 허용되지 않는다.

 

한 시스템에서 모든 프로세스에 의해 할당된 가상메모리의 양은 디스크 내의 스왑 공간의 양에 의해 제한된다.

 

이용도 U = 실제로 사용하는 힙의 크기 / 할당된 힙의 크기

이용도를 최대로 하면 최고 이용도가 된다.

 

9.9.4 단편화

 

나쁜 힙 이용도의 주요 이유는 단편화

외부 단편화가 발생하는 사례

출처 : https://www.researchgate.net/publication/305333536_Adaptive_memory_management_scheme_for_MMU-less_embedded_systems

 

 

내부 단편화 : 할당된 블록이 데이터 자체보다 더 클 때 일어난다.

외부 단편화 : 할당 요청을 만족시킬 수 있는 메모리 공간이 전체적으로 공간을 모았을 때는 충분한 크기가 존재할 때,

이 요청을 처리할 수 있는 단일한 가용블록은 없는 경우에 발생.

 

외부 단편화가 측정하기 어렵고 예측하기 불가능하기 때문에 할당기들은 대개 많은 수의 더 작은 가용 블록들보다는 더 적은 수의 더 큰 가용 블록들을 유지하려는 방법들을 채택하고 있다.

 

 9.9.6 묵시적 가용 리스트

 

묵시적 가용 리스트 : 가용 블록이 헤더 내 필드에 의해서 묵시적으로 연결

출처 : https://www.clear.rice.edu/comp321/html/laboratories/lab08/

Epilogue block : 전체 블록의 '끝'을 나타내는 블럭 헤더. 할당 비트를 가지고 크기 0을 갖는다.

Prologue block : 블럭 검색을 하기위한 시작점 (전역 변수)

 

9.9.11 경계 태그로 연결하기

 

출처 : https://www.clear.rice.edu/comp321/html/laboratories/lab08/

헤더와 풋터 사이즈와 할당 비트를 체크하여 가용 블럭을 연결시킬 수 있다.

 

9.9.13 명시적 가용 리스트

 

이중 연결 가용 리스트를 사용하는 힙 블록의 포맷

명시적 가용 리스트 : 가용 블록들을 명시적 자료구조로 구성하는 것

장점 : first fit 할당 시간을 전체 블록 수에 비례하는 것에서 가용 블록의 수에 비례하는 것으로 줄일 수 있다.

단점 : 최소 블록 크기가 커지고 잠재적인 내부 단편화 가능성이 증가한다.

 

 

글을 마치며,

 

chpater9에서 가상메모리와 힙 구성에 대한 학습을 했다.

포스팅한 내용 외에 분리된 가용 리스트, 가비지 컬렉션 등이 있다.

추가적인 학습을 하고싶다면, CS:APP 제 3판을 구매하는 것을 추천한다.

( 오역이 많기 때문에 영어에 친숙하신 분이라면 원서를 추천한다. )

또한 카네기 멜른 대학 강의를 들을 수 있다. ( 구글은 신이다 )

 

 

 

긴 글 읽어주셔서 감사드립니다.

22.12.06

댓글