| 가상 메모리, Page fault handling

 

[정리]

1. 주제

- Page fault는 왜 발생하는 것이며, page fault 발생시 kernel은 어떻게 동작 하는가

2. 전체 내용 요약

1) 이론 필기 내용 요약

2) page fault tracing 실습

3) page fault handler 과정 확인

 

 

[1) 이론 필기 내용 요약]

OS에선 physical memory를 할당 하는 것이 아닌, virtual memory를 할당 함

page fault는 VA <-> PA 매핑이 되어 있지 않기 떄문에 발생하는 것

Segmentation fault 또한 page fault의 일종

 

Virtual address를 사용시 장점

1) ABI (Application Binary Interface)

- OS, CPU, 컴파일러 등이 함께 약속된 규약 (SYSCALL, clling convension, VA, ELF ..)

- ABI를 적용함으로써 binary만 제공되어도 바로 사용이 가능한 것이다.

2) 메모리 절약

3) 보안

4) 메모리 확장 (swap disk 활용)

- file system format과는 전혀 관계 없음

 

$ ps -eo pdi,comm,vsz,rss | head -2

현재 동작중인 task에 대해 pid, command, vsz (virtual memory size), rss (resident set size)에 대해 확인

vsz는 virtual memory size를 나타내므로, 실제 task가 .bss, .data, .text 등 모든 section을 memory에 loading할시에 필요한 메모리 크기를 나타냄

 

[2) page fault tracing 실습]

kernel영역에서 발생하는 page fault에 대해 tracing

# cd /sys/kernel/debug/tracing/
# echo 1 > events/exceptions/page_fault_kernel/enable
# cat trace_pipe

(밑의 그림에서는 page_fault_kernel로 동작해 결과를 보여주지만,, 아래의 내용들은 kernel / user 유사한 부분이 많음)

address : page fault가 발생한 가상 주소

ip : page faule가 발생 했을 시점의 instruction 주소

error code :

$ vim ${linux}/arch/x86/include/asm/traps.h

위에서 발생한 error code=0x2의 의미는

error code : 0x2 = no page found + write + kernel mode access

커널 모드로 write를 수행하는데 page가 존재하지 않아 page fault가 발생함

 

이번에는 page fault가 발생한 부분에 대해 stacktrace를 사용해 call stack을 확인

기존 trace point 위치에서 실행
# echo 1 > options/stacktrace
# cat trace_pipe

copy_to_user 수행시 kernel mode에서 user 영역에 접근해 data를 write했을시 user 영역 주소가 존재하지 않아 page fault가 발생한 것임

보통 kernel 주소에 대해 page fault가 발생하는 경우는 거의 없음

 

[3) page fault handler 과정 확인]

$ vim ${linux}/arch/x86/entry/entry_64.S

page fault 발생시 page_fault가 호출되며, do_page_fault가 다시 호출되어 처리가 됨

이때, has_error_code, read_cr2는 밑의 do_page_fault함수의 argument (error_code = has_error_code, address = read_cr2)가 됨

cr2는 page fault를 일으킨 가상주소를 저장 함

$ vim ${linux}/arch/x86/mm/fault.c

page_fault -> do_page_fault -> __do_page_fault -> do_user_addr_fault의 순서로 동작

(참조: 수업 중 do_kern_addr_fault이 아닌 do_user_addr_fault에 대해서만 진행 됨)

task가 접근한 page fault 주소를 알고 있으며, 해당 address에 대해 task_struct -> mm_struct -> vma 영역 (text, stack, heap,...) 중 어느 영역에서 page fault가 발생 했는지 확인

handle_mm_fault -> .. -> __handle_mm_fault에서 VA-PA 변환테이블을 수정 함

조금 더 자세한 내용들은 뒤에 연속적으로 나옴

__handle_mm_fault -> handle_pte_fault -> do_anonymous_page에서 PA를 위한 page를 할당 받음

page 할당 이후 실제 page table entry 요소에 대해 업데이트 수행

 

위의 과정에 대해 다시 정리하자면

do_user_addr_fault()   : arch/x86/mm/fault.c

  -> handle_mm_fault()    :   mm/memory.c

      -> __handle_mm_fault()    :   mm/memory.c

          -> handle_pte_fault()     :   mm/memory.c

               -> ptep_set_access_flags()   :  arch/x86/mm/pgtable.c

                    -> set_pte() “페이지 테이블 한요소(pte) 수정”

 

 

+ Recent posts