이전 포스팅인 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
'CS > OS' 카테고리의 다른 글
[운영체제] Locks #2 (0) | 2021.06.11 |
---|---|
[운영체제] Locks #1 (2) | 2021.06.11 |
[운영체제] Page Replacement Policy (페이지 교체 알고리즘) (0) | 2021.06.09 |
[운영체제] Swapping (가상 메모리) (0) | 2021.06.09 |
[XV-6 운영체제] Copy-on-Write #1 (0) | 2021.06.04 |