8장의 contiguous, discontiguous memory allocation에 이어서 대부분의 OS에서 사용되는 Virtual memory organization, 주로 Demand paging에 대해서 알아보자.
프로세스 이미지를 100프로 다 로딩하지 않고 프로세스를 실행할 수 있게끔하는 기법이다.
조각난 이미지를 필요할 때 memory에 로딩하기 때문에 프로세스의 용량에 구애받지 않고 실행시킬 수 있다.
Virtual Memory에서는 프로세스를 block단위로 쪼개고 Block map table로 관리한다.
Residence bit
이 사용된다.먼저 CPU에서 프로세스를 실행하기 위해서 virtual address를 생성한다. 메모리 접근을 하기 위해서 block map table
의 residence bit을 살펴본다. 1이라면 real address 'a'에서 offset 'd'만큼 떨어진 위치인 physical address에 접근하게 된다.
residence bit == 0 이라면?
디스크에 가서 해당 block을 읽어 메모리에 가져와야한다. storage와 memory간의 데이터전송은 입출력이기 때문에 그 동안은 프로세스가 실행될 수 없다. 그렇기 때문에 이 떄 프로세스는 sleep상태가 되고 context switching이 발생하게 된다.
Pseudo-code로 요약하면 다음과 같다.
(paging으로도 얘기하기때문에 discontiguous allocation의 paging과 구분해야하는데, 최근엔 대부분 Virtual memory시스템을 사용하기 때문에 paging이라고 하면 demand paging을 생각하면 된다.)
program을 같은 사이즈의 block으로 나눈다.
프로그램 실행 시 처음엔 당장 필요한 page만 로딩하고 필요에 따라 page를 추가로 로딩한다.
용어
page frame
: 페이지와 같은 크기로 Main memory를 나눈 것pager
: 페이지 단위로 프로그램을 swap in/out하는 커널 모듈swapper
: 프로세스 전체를 swap해주는 모듈특징
Address mapping
Virtual address v=(p,d)
PMT(page map table) 사용
위에 page0,1,k만 메모리에 들어가있는 상황에 대한 PMT예시이다.
Address mapping기법
일반 block mapping과 똑같은데, PMT가 main memory의 kernel space(PCB)에 존재한다. Pseudo-code로 보면,
이 방식은 단점이 있는데,
첫 번째 단점을 해결하기 위해 TLB
를 사용하는 Associative mapping을 사용할 수 있다.
TLB전체를 모두 저장해둘 큰 용량의 TLB를 만들기가 쉽지 않기 때문에 두 기법을 적절히 합쳐서 사용하는 mapping 방법이다.
TLB를 먼저 확인해주고, 있다면 residence bit
을 검사해주는데, hit ratio가 90프로 이상으로 잘 나오기 때문에 대부분 1이다. TLB에 없다면 direct mapping 기법을 사용해 메모리의 PMT에서 가져와서 TLB로 이동시켜준다.
TLB search : 20ns
memory acess time : 100ns
라고 가정했을 때,
TLB말고도 address mapping 속도 개선을 위해 사용되는 방법들을 간단하게 보자
Page-table registers
Other page table structures <- page 크기 관련
Hierarchical paging
Virtual address가 32-bit이라고 가정할때, 다음과 같이 20bit가 page 번호를 저장하는데 사용되고, 12bit는 offset을 저장하는데 사용된다.
앞서 살펴본 것처럼 20bit면 대략 2^(20-1), 백만개 정도의 페이지 번호가 생성될 수 있는데 너무 많아 저장이 힘들기 때문에 20bit를 10bit, 10bit로 나눠서 관리하는 기법이다.
이런식으로 2-level로 계층화시켜서 관리해 메모리에 모든 page table을 로드해둘 필요가 없도록 한다.
Hashed page table
Inverted page table
보통 프로세스마다 page table을 하나씩 갖지만 Inverted page table
은 시스템에 하나의 page table을 유지시키는 방법이다. 원래는 residence bit를 확인했지만, 이 기법에서는 virtual address의 (pid , p)를 Inverted page table에서 찾고 있다면 그 주소를 기반으로 physical address와 매핑시키는 방법을 사용한다.
Demand paging기법이 해결해야할 몇 가지 이슈들이 있다.
라이브러리 함수같이 공용으로 사용하는 자원은 프로세스 이미지에 가지고있는 것보다 메모리 한 부분에 sharable pages
들을 올려놓고 같이 사용하도록 하는 것이 유리하다.
Sharable pages
Data page
Procedure pages : Pure code(reentrant code) <- 실행중에 자기 코드를 절대 바꾸지 않는 코드로, 있는 그대로 실행만 하는 코드로만 구성되어있어야 함
Data page가 아닌 code page를 실행하는 page일 경우 문제가 발생할 수 있다. 위 예시처럼 코드 영역에 branch가 있다면 p1입장에서는 jump 주소가 k1이여야 정상적으로 실행되고, p2 입장에서는 jump주소가 k2여야 정상적으로 실행된다.
그렇기 때문에 코드 페이지를 공유하는 경우에, 해당 페이지를 공유하려는 프로세스들은 아래 예시처럼 항상 같은 page frame 주소를 사용해야만한다.
Virtual memory시스템을 사용하면 하나의 기계어 명령을 실행하는 도중에 page fault가 발생했을 때 문제가 생길 수 있다.ADD 명령어는 위와같은 순서로 실행된다. 기계어 명령어는 atomic하게 실행되어야하기 때문에, 실행 도중에 page fault가 발생하게 된다면,
excepttion handling으로 fetch할 때 증가시켰던 program counter 값을 원위치로 복구시킨 다음 instruction을 restart해줘야한다.
즉 fetch 뿐만 아니라 기계어명령어를 실행하는 도중 CPU나 메모리에 영향을 준 값들을 모두 원상 복구 후에 context switching을 해야한다.
page fault로 인한 EAT(effective access time)에 대한 이슈다.
Memory access time = 100ns
Average paging service time : 8 millisec
page fault rate : p (0<= p <= 1)
이렇게 가정한다면,
EAT
= (1-p) x ma + p x pagingTime
= (1-p) x 100 + p x 8,000,000 = 100 + 7,999,900 x p
-> page fault(p)가 1/1000 일때, EAT
= 8.1 microsec
1/1000의 낮은 확률로 page fault가 발생하는데도 80배가 느려진다.
1분 걸리는 process를 virtual memory기법을 사용하면 80분이 걸린다고 생각하면 너무하다.
10프로 정도만 성능저하가 있도록 하는 page fault 확률을 위 방식대로 계산해보면
p = 1/800,000 가 돼야한다. 이렇게 page fault를 줄이는 방법은 10장에서 다룰 예정이다.
paging system에서 fork()를 할때는 CoW
기법을 사용한다.