메모리 계층은 레지스터, 캐시, 주기억장치, 보조기억장치로 구성되어 있다. 레지스터와 캐시는 CPU가 관리하고 주기억장치와 보조기억장치는 OS가 관리한다.
Block : 하드 디스크와 메모리 사이의 데이터 전송 단위(1~4KB)
Word : 메모리와 레지스터 사이의 데이터 전송 단위(16~64bits) -> 32bits, 64bits 컴퓨터
보호
주소 변환
외부 단편화를 줄이기 위한 할당 방식
최초 적합(First fit) : 할당할 프로세스 크기보다 크거나 같은 hole을 탐색하되 가장 먼저 찾은 hole에 프로세스를 할당하는 방식
최적 적합(Best fit) : 할당할 프로세스 크기와 hole 크기의 차이가 가장 작은 hole에 프로세스를 할당하는 방식
최악 적합(Worst fit) : 최적 적합과 반대로, 할당할 프로세스 크기와 hole 크기의 차이가 가장 큰 hole에 프로세스를 할당하는 방식
속도와 효율성 측면에서 first fit과 best fit이 좋지만, 외부 단편화로 인해 전체 메모리의 1/3이 낭비된다고 한다.
페이징 기법을 사용하기 위해서 여러 개로 흩어진 페이지에 CPU가 접근하기 위해서 페이지 테이블을 통해 논리주소를 물리 주소로 변환해야 한다.
🤔 논리 주소는 2진수로 표현되고 m 비트로 이루어져 있다고 가정한다. 논리 주소 50번지는 물리 주소로 몇 번지일까?
-> 50은 이진수로 110010(2)이다. page size가 16 = 2^4 bytes이므로 d는 4칸으로 0010(2)이 된다. p는 d를 제외한 나머지 상위 2칸인 11(2)이 된다. p는 11(2) 즉, 십진수로 3이되고 page table에 따라 f = 8, 이진수로 1000(2)이 된다. d는 그대로다. 따라서 물리 주소는 이진수로 1000,0010(2), 10진수로 130번지가 된다.
페이징 기법을 사용하면 내부 단편화가 발생한다. 예를 들어 페이지 크기가 500byte이고 프로세스 A가 1300byte의 메모리를 요구한다면 2개의 frame(500 * 2 = 1000) 하고도 300byte가 모자라기 때문에 총 3개의 frame이 필요하다. 하지만 3번째 프레임에는 200(500-300)의 여유 공간이 발생하는데 이를 내부 단편화라 부른다. 내부 단편화는 해결할 방법이 없지만 외부 단편화에 비해서 낭비되는 메모리 공간이 매우 적다.
레지스터로 페이지 테이블을 만들 경우
메모리 내부에 페이지 테이블을 만들 경우
따라서 페이지 테이블을 캐시로 만들어 CPU와 메모리 사이에 위치시키는데 이러한 테이블을 TLB(Translation Look-aside Buffer) 라고 부른다. 이는 레지스터일 때보다 변환 속도는 느리고 메모리일 때보다 테이블 크기는 작지만, 레지스터일 때보다 테이블 크기가 크고 메모리일 때보다 변환 속도가 빠르다.
세그멘테이션에서는 프로세스를 논리적인 단위로 나누기 때문에 세그먼트의 크기가 다양하므로 외부 단편화 문제가 발생한다. 따라서 오늘날에는 세그멘테이션보다는 페이징 기법을 주로 사용한다. 세그멘트를 페이징 기법으로 나누는 두 가지를 합친 방식인 Paged segmentation도 있다. 하지만 세그먼트와 페이지가 동시에 존재하기 때문에 주소 변환도 두번 해야 한다. 즉 CPU에서 세그먼트 테이블에서 주소 변환을 하고, 그다음 페이지 테이블에서 또 주소 변환을 해야 한다.
가상 메모리는 물리 메모리 크기의 한계를 극복하기 위해 나온 기술로 이를 활용하면 100MB 메모리 크기에 200MB 크기의 프로세스를 수행할 수 있다. 가상 메모리의 핵심은 필요한 부분만 메모리에 적재하는 것이다. 단위는 페이지 혹은 세그멘트 둘 다 가능하지만 오늘날에는 대부분 페이지 단위를 사용한다. 이처럼 현재 필요한 페이지만 메모리에 올리는 것을 Demanding Paging(요구 페이징)이라고 하며 가상 메모리로 통용해서 부른다.
Demanding Paging에서는 앞서 살펴본 페이징 기법의 page table에 valid bit가 추가되었다. 이는 현재 메모리에 페이지가 있는지 없는지를 나타내는 비트이다. 현재 페이지가 메모리에 있다면 1, 없다면 0값을 갖는다.
Page fault는 위에서 살펴본 CPU가 접근하려는 페이지가 메모리에 없는 경우이다. 즉, 페이지 테이블의 valid bit 값이 0인 경우이다. 아래는 page fault 과정을 나타낸다.
Swapping vs Demanding Paging
공통점 : 둘 다 메모리와 backing store 사이의 상호작용
차이점 : Swapping은 프로세스 단위로 이동하고 Demanding Paging은 페이지 단위로 이동
메모리가 꽉 차면 이미 메모리에 있는 페이지 중 하나를 다시 backing store에 보내고(page-out), 새로운 페이지를 메모리에 올려야한다(page-in). 이를 페이지 교체라고 한다.
Optimal 알고리즘은 가장 좋은 알고리즘이라고 일컫는 알고리즘이며 이는 가장 먼 미래에
참조되는 페이지와 현재의 페이지를 바꾸는 알고리즘(LFD, Longest Forward Distance)이다. 예를 들어 0, 1, 2, 3, 4, 2 이렇게 들어온다고 가정하면 가장 미래에 참조되는 2와 스와핑하는 것을 말한다. 그러나 미래에 사용되는 프로세스를 우리는 알지 못한다. 따라서 사용할 수 없는 알고리즘이다.
FIFO(First In First Out) 알고리즘은 가장 먼저 온 페이지부터 교체한다.
LRU(Least Recently Used) 알고리즘은 최근에 사용되지 않은 페이지 즉, 참조가 오래된 페이지를 바꾼다. 이를 위해서 각 페이지마다 최근 사용한 횟수를 나타내는 자료구조를 따로 만들어야 할 수도 있다. 예를 들어 7 0 1 2 0 3 0 4로 페이지 요청이 들어온다고 가정하고 4개의 페이지만 담는다고 가정하면 아래와 같이 된다.
LRU에서 발전한 알고리즘이자 NUR(Not Used recently) 또는 NRU(Not Recently Used)
라고도 불리는 알고리즘이다. 일명 clock 알고리즘이라고 하며 먼저 0과 1을 가진 비트를 둔다. 1은 최근에 참조되었고 0은 참조되지 않음을 의미한다. 만약 한 바퀴 도는 동안 사용되지 않으면 0이 된다. 시계 방향으로 돌면서 0을 찾고 0을 찾은 순간 해당 페이지를 교체하고, 해당 부분을 1로 바꾸는 알고리즘이다.
LFU(Least Frequently Used) 알고리즘은 가장 참조 횟수가 적은 페이지를 교체하는
알고리즘이다. 예를 들어 0, 1, 2, 0, 0, 1, 2, 3 이렇게 들어오고 3개의 페이지밖에 없다고 하면 다음과 같이 교체된다.