CS/OS

[XV-6 운영체제] Copy-on-Write #2 구현

Henu 2021. 6. 4. 23:17
 

[XV-6 운영체제] Copy-on-Write #1

Copy-on-Write가 어떤 기능을 하는지 알아보자 Copy on Write는 기본적으로 forks 기능과 관련이 있다. forks는 parent process를 이용해서 child process를 만들어 내는 것으로 볼 수 있다. (기본적으로 복제를..

hyeo-noo.tistory.com

 

이전 포스팅인 Copy-on-Write에 대한 설명에 이어서 Copy-on-Write를 구현해 보겠다.

 


1.  vm.c 수정

 

page table entry(PTE)에 writeable flag(PTE_W)를 disable (read-only 상태로 만들어준다)

새로운 page 할당없이 parent process의 page를 child process의 mapping table에 매핑

physical page의 reference count 증가

lcr3(V2P(pgdir))를 호출해 TLB를 flush

 

// vm.c copyuvm()

 

새로운 page를 할당해서 mem에 입력하는 과정과 memmove를 통해 할당된 page를 복사하는 과정을 주석 처리 했다.

 

새로 매핑되는 child process의 PTE의 writeable flag를 disable 시킨다

이 때 해당 page에 write를 시도하면 page fault가 발생하고 Copy-on-Write가 수행되게 해야한다. (page fault handler 에서 해야할 일)

 

child process의 page table에 pa(parent process의 physical page address)를 넘겨준다.

 

inc_refcounter를 통해서 연결된 physical page의 reference count 를 1 증가 시켜주었다.

 

lcr3()를 통해서 TLB를 초기화 해주었다.

 

 

Pagefault 핸들러 추가

 

// pagefault()

rcr2()를 호출해 pagefault가 발생한 가상주소를 가져온다

 

가상주소가 유효한 값인지 확인한다

 

해당 가상주소의 page table entry(pte_t) 찾기 - walkpgdir()를 통해서 가져올 수 있다.

walkpgdir(pgdir, va, 1) : 가상주소와 page directory를 주면 해당 주소가 속한 pte를 반환

 

구한 pte를 통해서 physical address를 찾고, 해당 주소에 대한 reference counter를 가져온다

 

reference count가 1보다 큰 경우

- 새로운 페이지를 할당 받아 기존 페이지를 복사

  >> kalloc(), memmove() (기존의 copyuvm에서 주석처리 했던것을 가져옴)

- pte에 physical address 내용을 업데이트 해준다

- reference count 1 감소(이제 각자 다른 page를 사용하기 때문)

 

reference count가 1인 경우

- 현재 pte의 writeable flag만 enable (혼자 사용하고 있으므로 문제가 없다)

 

 


2.  kalloc.c 수정

 

Physical page에 대한 Reference count 제어

 

// kalloc.c  전역변수

먼저 각 physical page의 reference counter를 기록할 배열이 필요하기 때문에 총 physical page의 개수만큼의 배열을 만들어 주었다.

앞으로 주어진 physical address를 PGSHIFT만큼 오른쪽 SHIFT를 해 주면 해당 물리주소의 reference count값을 얻을 수 있다.

 

// kalloc.c

 

Reference counter관련 API를 구현하였다.

 

위에서 부터 차례로

  • pa에 속한 physical page의 reference counter를 반환
  • physical page의 reference counter를 1 감소
  • physical page의 reference counter를 1 증가

 

구현 후 def.h에 프로토 타입을 선언해 주었다.

 

 

// kalloc.c  freerange()

 

freerange는 초기에 physical page를 초기화 해주는 동작을 수행하므로

 

해당 페이지에 대한 reference counter도 초기화 해주어야 한다.

 

 

// kalloc.c  kfree()

 

먼저 해당 page의 reference count를 1 감소시키고 

 

page에 대한 reference count가 0이 된 경우에만 freelist에 추가시킬 수 있게 만들었다.

 

reference count를 1 감소시킬 때 0보다 클 때만 감소시킨다는 조건을 걸어주지 않으면 XV6가 실행이 안되니 조심하자.

그리고 0보다 클 때가 아니라 1보다 클 때로 조건을 잡으면 test2가 WRONG이 나오게 된다.

 

 

// kalloc.c  kalloc()

 

새로운 page를 할당하고 해당 page를 freelist에서 빼는 동작을 수행하는데 

 

추가적으로 해당 page에 대한 reference counter를 1로 초기화 해주는 동작도 수행해야한다

 


3. trap.c 수정

// trap.c  trap()

 

pagefault가 발생한 경우 pagefault() 가 실행 될 수 있게 수정

 


 

성공!

 

Copy-on-Write