2025. 3. 7. 23:01ㆍCS/OS
페이지 테이블 | OS in 1,000 Lines
operating-system-in-1000-lines.vercel.app
앞서 “[1000줄 OS 구현하기] 프로세스”에서 간단한 멀티프로세싱을 구현해 보았다.
Paging으로 가상 메모리를 관리하는 기능을 학습하고 구현해 보자.
1. 메모리 관리와 가상 주소
프로그램이 메모리에 접근할 때, CPU는 지정된 가상 주소(논리 주소)를 물리 주소로 변환한다.
이를 주소 바인딩(Address Binding), 주소 변환이라고 한다.
가상 주소와 물리 주소를 매핑하는 페이지 테이블이 필요하다.
2. 이론
교안에서는 RISC-V의 페이징 메커니즘 중 하나인 Sv32를 사용했다.
Sv32는 2단계 page table로 구성된다.
구현에 앞서 가상 주소 구조와 two or Multi-level paging에 대한 이론을 정리해 보았다.
가. 가상 주소 구조
위 이미지는 가상 주소로부터 물리 주소를 찾아내는 원리를 단순하게 보여주는 그림이다.
페이지 테이블에서 가상 주소(page number)에 해당하는 물리 주소 값(frame number)을 찾아내는 방법이다.
물리 메모리에서 페이지가 들어갈 수 있는 공간을 frame이라고 한다.
Page table의 엔트리들이 메모리상에 연속적으로 저장되어 있기 때문에 인덱스로 사용하여 바로 접근 가능하다.
실제로는 TLB(Translation Lookaside Buffer)를 사용하여 캐싱한다.
TLB()는 가상 주소와 물리 주소의 매핑 정보를 저장하는 고속의 캐시 메모리이다.
자주 변환되는 주소를 캐시에 저장해 두어 메모리 접근 시간을 크게 줄일 수 있다.
TLB는 CPU 내부에 위치한다.
반면 TLB는 전체 page table 중에서 일부만 가지고 있기 때문에 인덱스로 random access가 불가능한다.
대신 Associative Register를 사용해서 병렬적으로 page를 검색한다.
TLB 장점 | TLB 단점 |
병렬 검색. 메모리 접근 시간 단축 | 하드웨어 구현이 복잡하고 비쌈 |
높은 적중률 (Locality로 인해 80-99%의 적중률) | 컨텍스트 스위칭 시 TLB 플러시 필요 |
멀티레벨 페이징의 오버헤드 감소 | 제한된 엔트리 수로 인한 용량 한계 |
나. Two-Level Page Table
Two-Level Page Table에서는 page table이 2개 있어서 주소 변환 시 page table을 2번 거친다.
Two-Level Page Table을 사용하는 주된 이유는 메모리 공간의 효율성 때문이다.
Single-level page table의 경우 프로세스의 전체 주소 공간에 대한 페이지 테이블 엔트리를 연속적으로 저장해야 하기 때문에 많은 메모리 공간이 필요하다.
인덱스로 접근하기 때문에 연속적일 필요가 있다.
반면 Two-level page table은 실제 사용되는 페이지 테이블 엔트리만 생성할 수 있어서 메모리를 절약할 수 있다.
가상 메모리의 특성상 각 프로세스마다 자신만의 가상 메모리 공간을 가지는데, 실제로 사용되는 page table entry만 생성할 수 있어서 메모리 공간을 아낄 수 있다.
또 여러 개의 작은 page table로 분리함으로써 모든 엔트리를 연속적으로 저장하지 않고, 여러 개의 작은 연속적인 테이블로 나눌 수 있다.
Two-level page table의 주소 변환 과정은 다음과 같다:
- CPU는 가상 주소를 생성한다. 이 주소는 2개의 page number와 page offset 하나로 구성된다.
- 1단계 page number을 사용해 2단계 page table의 기본 주소를 찾는다.
- 찾은 2단계 page table 기본 주소와 2단계 page number을 사용해 frame number를 찾는다.
- frame num와 offset을 조합하여 최종 물리 주소를 얻는다.
다. Multi-Level Page Table
Multilevel Paging를 사용하는 이유는 같은 맥락으로 메모리 공간을 효율적으로 사용하고 페이지 테이블의 크기를 줄이기 위해서다.
하지만 page 단계가 늘어날수록 메모리 접근 횟수가 늘어난다.
예를 들어서 4단계 페이지 테이블 사용한다면, 메모리에 접근하기 위해서 5번의 접근이 필요하다.
이를 극복하기 위해서 TLB를 사용해 접근 시간을 줄인다.
라. Vitual Memory와 가상 주소
가상 메모리는 보조 저장장치에 swap 영역을 설정하고 해당 영역을 메모리와 같이 사용할 수 있는 방법을 제공한다.
RAM과 Swap 영역에 물리 주소를 부여하고, MMU가 이 물리 주소와 프로세스의 가상 주소를 매핑하여 관리합니다.
이를 통해 프로그래머가 실제 물리적 메모리 구조를 신경 쓰지 않고 프로그래밍할 수 있다.
하지만 가상 주소도 결국엔 실제 물리 주소로 변환되어야 하며, 이 물리 주소는 32비트 시스템에서 4GB가 한계다.
가상 메모리를 사용해 Swap 영역을 사용해도 4GB를 넘는 주소 공간을 사용할 수 없다.
64비트 시스템을 사용하면 이러한 메모리 제약을 극복할 수 있다.
💡 가상 메모리의 크기
Q. 스왑 영역을 무한대로 추가할 수 있다?
A. 32비트 시스템에서는 최대 4GB (2^32 바이트)의 물리적 메모리 주소 공간을 가질 수 있다. 가상 메모리를 사용하더라도 결국 가상 주소는 물리 주소로 변환된다. 이에 스왑 영역을 포함한 가상 메모리 주소 공간은 4GB 한계를 넘을 수 없다.
Q. 프로세스마다 저마다의 가상 메모리를 가지니 프로세스를 늘리면 전체 가상메모리의 합은 무한히 커질 수 있지 않은가?
A. 논리적으론 그럴 순 있지만 의미가 없다. 결국 가상 주소는 물리 주소로 변환된다. 가상 주소에 매핑될 물리 주소는 한계가 있다. 서로 다른 가상 주소가 같은 물리 주소로 중복 매핑되는 이상한 생각을 해볼 순 있지만, 그렇다고 해서 근본적인 한계를 넘을 순 없다.
3. 구현
가. 페이지 테이블 구성하기
“교안에서는 RISC-V의 페이징 메커니즘 중 하나인 Sv32를 사용했다”라고 언급했다.
32비트 가상 주소는 1단계 페이지 테이블 인덱스(VPN[1]
), 2단계 인덱스(VPN[0]
), 그리고 페이지 오프셋 (offset
)으로 나뉜다.
VPN은 Virtual Page Number을 줄임말이다.
총 32bit로 이루어진 메모리 주소에 VPN[1]
와 VPN[0]
가 10bit, offset
가 12bit를 차지한다.
먼저 매크로부터 정의한다.
- kernel.h
#define SATP_SV32 (1u << 31)
#define PAGE_V (1 << 0) // "Valid" 비트 (엔트리가 유효함을 의미)
#define PAGE_R (1 << 1) // 읽기 가능
#define PAGE_W (1 << 2) // 쓰기 가능
#define PAGE_X (1 << 3) // 실행 가능
#define PAGE_U (1 << 4) // 사용자 모드 접근 가능
각 매크로 정의의 비트 연산을 설명하면:
1u << 31
: 부호 없는 정수 1을 31비트 왼쪽으로 시프트1 << 0
: 1을 0비트 왼쪽으로 시프트 (즉, 1)1 << 1
: 1을 1비트 왼쪽으로 시프트 (즉, 2)1 << 2
: 1을 2비트 왼쪽으로 시프트 (즉, 4)1 << 3
: 1을 3비트 왼쪽으로 시프트 (즉, 8)1 << 4
: 1을 4비트 왼쪽으로 시프트 (즉, 16)
비트는 0부터 세기 때문에 1u << 31
은 32번째 비트를 의미한다.
SATP_SV32
는 최상위 비트(31번째 비트)를 1
로 설정하여 10000000 00000000 00000000 00000000
와 같은 형태가 된다.
이렇게 각각의 비트를 다른 위치에 설정함으로써 페이지의 서로 다른 권한과 속성을 나타내는 플래그로 사용한다.
특히 SATP_SV32
는 satp
레지스터에서 "Sv32 모드 페이징 활성화"를 나타내는 비트이다.
satp
는 Supervisor Address Translation and Protection register의 줄임말이다.
Sv32 모드 페이징 활성화는 RISC-V 프로세서에서 32비트 가상 메모리 시스템을 활성화하는 설정이다.
이 모드가 활성화되면…
- CPU가 생성하는 모든 메모리 주소를 가상 주소로 취급
- 메모리 접근 시 항상 페이지 테이블을 통한 주소 변환 수행
- 2단계 페이지 테이블을 사용하여 가상 주소를 물리 주소로 변환
- 메모리 보호 및 접근 권한 검사 기능 활성화
이를 통해 프로세스 간 메모리 격리와 보안을 제공할 수 있다.
나. 페이지 매핑하기
void map_page(uint32_t *table1, uint32_t vaddr, paddr_t paddr, uint32_t flags) {
if (!is_aligned(vaddr, PAGE_SIZE))
PANIC("unaligned vaddr %x", vaddr);
if (!is_aligned(paddr, PAGE_SIZE))
PANIC("unaligned paddr %x", paddr);
uint32_t vpn1 = (vaddr >> 22) & 0x3ff;
if ((table1[vpn1] & PAGE_V) == 0) {
// Create the non-existent 2nd level page table.
uint32_t pt_paddr = alloc_pages(1);
table1[vpn1] = ((pt_paddr / PAGE_SIZE) << 10) | PAGE_V;
}
// Set the 2nd level page table entry to map the physical page.
uint32_t vpn0 = (vaddr >> 12) & 0x3ff;
uint32_t *table0 = (uint32_t *) ((table1[vpn1] >> 10) * PAGE_SIZE);
table0[vpn0] = ((paddr / PAGE_SIZE) << 10) | flags | PAGE_V;
}
uint32_t *table1
: 전역 변수로 페이지 테이블을 관리하지 않고 함수 인자로 전달
: 프로세스들이 각자의 페이지 테이블을 가질 수 있도록 하기 위함.
: 각 프로세스는 자신만의 독립된 가상 주소 공간을 가지기 때문.paddr_t
: 물리 메모리 주소를 나타내는 타입.vaddr_t
: 가상 메모리 주소를 나타내는 타입. 표준 라이브러리의uintptr_t
에 해당.is_aligned()
: “[1000줄 OS 구현하기] C 표준 라이브러리”에서 다룬 내용.uint32_t vpn1 = (vaddr >> 22) & 0x3ff;
: 가상 주소에서 1단계 페이지 테이블 인덱스를 추출.
: 상위 10비트를 얻기 위해 22비트 오른쪽으로 시프트.
:0x3ff
(1023 - 11 11111111)와 AND 연산.if ((table1[vpn1] & PAGE_V) == 0) {
: 1단계 페이지 테이블 엔트리가 유효한지 확인.
:PAGE_V
비트가0
이면 2단계 페이지 테이블이 없다는 의미.uint32_t pt_paddr = alloc_pages(1);
: 새로운 2단계 페이지 테이블을 위한 물리 메모리 페이지 할당table1[vpn1] = ((pt_paddr / PAGE_SIZE) << 10) | PAGE_V;
: 1단계 페이지 테이블 엔트리에 2단계 페이지 테이블에 관한 정보를 저장.
:(pt_paddr / PAGE_SIZE)
는 2단계 페이지 테이블이 할당받은 물리 페이지 번호를 구하는 방법.
: 10비트 왼쪽으로 시프트하는 이유는 페이지 테이블 엔트리의 비트 레이아웃에서 물리 페이지 번호(PPN)가 상위 비트들을 차지하고, 하위 비트들은 페이지 속성 플래그(Valid, Read, Write, Execute, User 등)를 저장하기 위해 예약되어 있기 때문.
: 유효 비트 1로 설정
uint32_t vpn0 = (vaddr >> 12) & 0x3ff;
: 가상 주소에서 2단계 페이지 테이블 인덱스를 추출.
: 중간 10비트를 얻기 위해 12비트 오른쪽으로 시프트 후0x3ff
(1023 - 11 11111111)와 AND 연산.uint32_t *table0 = (uint32_t *) ((table1[vpn1] >> 10) * PAGE_SIZE);
:table0
포인터에 2단계 페이지 테이블의 물리 주소를 계산해 저장.table0[vpn0] = ((paddr / PAGE_SIZE) << 10) | flags | PAGE_V;
: 2단계 페이지 테이블 엔트리에 frame number와 권한 정보를 저장.
map_page(uint32_t *table1, uint32_t vaddr, paddr_t paddr, uint32_t flags)
은 호출 전에 이미 데이터가 저장될 가상 주소와 물리 주소 모두가 할당된 상태다.
다. 커널 메모리 영역 매핑
커널을 위해서도 페이지 테이블 설정해야 함.
교안에서는 커널 메모리 매핑을"커널의 가상 주소 == 물리 주소"
로 동일하게 설정했음.
이렇게 하면 페이징을 활성화해도 기존의 코드는 물리 주소, 가상 주소 구분 없이 문제없이 동작한다.
- kernel.ld
ENTRY(boot)
SECTIONS {
. = 0x80200000;
__kernel_base = .; <- 추가
커널 링커 스크립트를 수정해 커널이 사용하는 시작 주소(__kernel_base
)를 정의.
- kernel.h
struct process {
int pid;
int state;
vaddr_t sp;
uint32_t *page_table; // 추가
uint8_t stack[8192];
};
(kernel.c에 있었던 것 같은데 kernel.h로 옮긴 듯)
프로세스 구조체에 1단계 page table의 주소를 저장하는 포인터 추가.
이로서 프로세스 별로 고유의 page table과 virtual memory를 가질 수 있다.
- kernel.c
extern char __kernel_base[]; // 추가
struct process *create_process(uint32_t pc) {
/* omitted */
// Map kernel pages.
uint32_t *page_table = (uint32_t *) alloc_pages(1); // 추가
for (paddr_t paddr = (paddr_t) __kernel_base; // 추가
paddr < (paddr_t) __free_ram_end; paddr += PAGE_SIZE) // 추가
map_page(page_table, paddr, paddr, PAGE_R | PAGE_W | PAGE_X); // 추가
proc->pid = i + 1;
proc->state = PROC_RUNNABLE;
proc->sp = (uint32_t) sp;
proc->page_table = page_table; // 추가
return proc;
}
프로세스를 생성할 때 새로운 1단계 페이지 테이블을 생성한다.
for (paddr_t paddr = (paddr_t) __kernel_base; // 추가
paddr < (paddr_t) __free_ram_end; paddr += PAGE_SIZE) // 추가
map_page(page_table, paddr, paddr, PAGE_R | PAGE_W | PAGE_X); // 추가
새로운 프로세스가 생성될 때마다 각 프로세스 별로 커널 페이지를 매핑하는 작업을 수행한다.
__kernel_base
부터 __free_ram_end
까지의 물리 메모리 영역을 순회하며 페이지를 매핑한다.
매핑된 페이지들은 읽기(R), 쓰기(W), 실행(X) 권한을 모두 부여하고 있다. (보안상 취약해 보이는데?)
커널 페이지를 매핑하므로서 .text
같은 정적 할당 영역과 alloc_pages
로 관리되는 동적 할당 영역까지 모두를 페이지로 접근할 수 있다.
각 프로세스마다 각자의 가상 메모리를 가진다.
프로세스는 생성 시 각자 1단계 페이지 테이블을 생성한다.
각 프로세스의 PCB에 1단계 페이지 테이블의 주소(물리 == 가상)를 저장한다.
context switching 시 satp 레지스터에 프로세스의 1단계 페이지 테이블 정보가 올라간다.
1단계, 2단계 페이지 테이블은 alloc_pages()
를 통해 memory 섹션에 페이지를 할당받아 생성되고, 프로세스는 1단계 페이지 테이블 정보를 BSS 섹션의 PCB에 보관한다.
라. 페이지 테이블 전환
이제 context switching 시 프로세스의 페이지 테이블도 스위칭해야 한다.
void yield(void) {
/* 생략 */
__asm__ __volatile__(
"sfence.vma\n" // 추가
"csrw satp, %[satp]\n" // 추가
"sfence.vma\n" // 추가
"csrw sscratch, %[sscratch]\n"
:
: [satp] "r" (SATP_SV32 | ((uint32_t) next->page_table / PAGE_SIZE)), // 추가, 끝에 꼭 콤마가 있어야 함!
[sscratch] "r" ((uint32_t) &next->stack[sizeof(next->stack)])
);
switch_context(&prev->sp, &next->sp);
}
sfence.vma\n
: TLB를 무효화하는 명령어.
: TLB에 저장된 주소 변환 캐시를 모두 flush함.
: 각 프로세스는 자신만의 페이지 테이블을 가지고 있어서, context switching 시 TLB도 flush 해야 함.csrw satp, %[satp]\n
: satp 레지스터에 새로운 프로세스의 1단계 페이지 테이블의 주소를 설정.SATP_SV32 |
: Sv32 모드 활성화.((uint32_t) next->page_table / PAGE_SIZE)),
: 다음 프로세스의 1단계 페이지의 PPN.
참고로, 커널 시작 시에는 satp 레지스터가 설정되어 있지 않아 페이징이 비활성화된 상태임.
따라서 처음으로 yield()
가 호출되기 전까진 Sv32 모드가 꺼져있어 물리 주소로 동작함.
4. 테스트
출력 자체는 이전 chapter와 다르지 않다.
따라서 정상적으로 동작하는지 알려면 페이지 테이블 내용 확인해야 한다.
가. satp 레지스터 값 확인하기
$ ./run.sh
// qemu 전환 : Ctrl + a + c
(qemu) stop
(qemu) info registers
...
sscratch 80204a6c
satp 80080243
Ctrl + a + c
→ stop
→ info registers
→ satp
값 확인
RISC-V의 satp 레지스터의 초기 부팅 시 값은 0
이다.
80080243
이 satp에 저장되어 있다. (사람마다 다를 수 있음)
context switching을 위한 yield()
함수가 호출되기 전까지는 Sv32 모드가 꺼져있다.
이 부분이 0
은 아니라면 정상적으로 동작했다.
💡SECTIONS { . = 0x80200000;의 숨겨진 의미.
이제 링커 스크립트가 SECTIONS { . = 0x80200000;로 시작한 이유를 추측할 수 있다.
커널의 시작 주소인 0x80200000은 0x80000000 이상의 높은 주소 영역에 위치하는데, 이는 물리 주소와 가상 주소를 동일하게 매핑하기 위함이다.
이러한 1:1 매핑 덕분에 페이징이 활성화되더라도 커널 코드가 정상적으로 실행될 수 있다.
나. 페이지 테이블 확인하기
1) 1단계 페이지 테이블 주소 구하기
1단계 페이지 테이블의 물리 주소는 (satp & 0x3fffff) * PAGE_SIZE
다.
0x3fffff
는 00111111 11111111 11111111
와 같고 아래 22비트를 추출한다.
PAGE_SIZE
는 4KB이고 4096은 16진수로 0x1000
이다.
(0x80080243 & 0x3fffff) * 4096
한 0x80243000
이 현재 설정된 1단계 페이지 테이블의 물리 시작 주소다. (4096
= 0x1000
)
2) 2단계 페이지 테이블 주소 구하기
1단계 페이지 테이블에서
__kernel_base
즉,0x80200000
이 위치한 곳을 찾아가 보자.
0x80200000
의 VPN1 = 0x80000000 >> 22 = 2^9 = 512
로 512번째 entry를 가리킨다.
각 entry는 4바이트이므로 512 * 4
를 더한 위치를 살펴본다.
1단계 페이지 테이블(0x80243000
)에서 512번째 entry에서 2단계 페이지 테이블의 정보를 찾는다.
(qemu) xp /x 0x80243000+512*4
0000000080243800: 0x20091001
0x20091001
는 table1[vpn1] = ((pt_paddr / PAGE_SIZE) << 10) | PAGE_V;
의 계산을 거친 값이 저장되어 있다.
정확한 2단계 페이지 테이블의 주소값 = (0x20091001 >> 10) * 4096 = 0x80244000
이다.
3) frame number 구하기
가상 주소(0x80200000
)의 VPN0은 (0x80200000 & 0x3ff000) >> 12 = 0x200 = 512
이다.
각 entry는 4바이트이므로 512 * 4
를 더한 위치를 살펴본다.
(qemu) xp /x 0x80244000+512*4
0000000080244800: 0x200800cf1
0x200800cf1
는 table0[vpn0] = ((paddr / PAGE_SIZE) << 10) | flags | PAGE_V;
계산을 거친 값이 저장되어 있다.
4) data 구하기
가상 주소(0x80200000
)의 오프셋은 0x80200000 & 0xfff = 0x000
이다.
최종적인 물리 주소는 페이지 테이블에서 얻은 프레임 번호에 오프셋을 더한 값이 된다.
즉, __kernel_base
의 실제 물리 주소 = (0x200800cf1 >> 10) * 4096 + 0x000 = 0x80200000
다.
(qemu) xp /1024x 0x80200000
0000000080200000: 0x80231537 0xacc50513 0x006f812a 0x000065a0
0000000080200010: 0xfcc10113 0xc222c006 0xc64ac426 0xca52c84e
0000000080200020: 0xce5acc56 0xd262d05e 0xd66ad466 0x2023d86e
0000000080200030: 0xa1030025 0x40820005 0x44a24412 0x49c24932
0000000080200040: 0x4ae24a52 0x5b824b72 0x5ca25c12 0x5dc25d32
0000000080200050: 0x03410113 0x15378082 0x28038020 0x2603a405
0000000080200060: 0x15b70008 0x56938020 0x82f541f6 0x9ae196b2
0000000080200070: 0x40d606b3 0x00469713 0x96ba06b6 0x80201737
0000000080200080: 0xa4c70713 0x42c896ba 0xa3c5a583 0x15634785
0000000080200090: 0x428800f5 0x14a04d63 0x00160513 0x41f55693
00000000802000a0: 0x96aa82f5 0x8d159ae1 0x00451693 0x96aa0536
00000000802000b0: 0x43489736 0x00f51a63 0x80201537 0xa4c50513
00000000802000c0: 0x428896aa 0x12a04563 0x00260513 0x41f55693
00000000802000d0: 0x96aa82f5 0x8d159ae1 0x00451693 0x95360536
00000000802000e0: 0x802016b7 0xa4c68713 0x00a706b3 0x478542c8
00000000802000f0: 0x00f51563 0x4c634288 0x05130ea0 0x56930036
0000000080200100: 0x82f541f5 0x9ae196aa 0x16938d15 0x05360045
0000000080200110: 0x973696aa 0x1a634348 0x153700f5 0x05138020
0000000080200120: 0x96aaa4c5 0x44634288 0x05130ca0 0x56930046
0000000080200130: 0x82f541f5 0x9ae196aa 0x16938d15 0x05360045
0000000080200140: 0x16b79536 0x87138020 0x06b3a4c6 0x42c800a7
0000000080200150: 0x15634785 0x428800f5 0x08a04b63 0x00560513
0000000080200160: 0x41f55693 0x96aa82f5 0x8d159ae1 0x00451693
0000000080200170: 0x96aa0536 0x43489736 0x00f51a63 0x80201537
0000000080200180: 0xa4c50513 0x428896aa 0x06a04363 0x00660513
0000000080200190: 0x41f55693 0x96aa82f5 0x8d159ae1 0x00451693
00000000802001a0: 0x95360536 0x802016b7 0xa4c68713 0x00a706b3
00000000802001b0: 0x478542c8 0x00f51563 0x4a634288 0x061d02a0
00000000802001c0: 0x41f65513 0x95328175 0x8e099961 0x00461693
00000000802001d0: 0x96b20636 0x43489736 0x00f51a63 0x80201537
00000000802001e0: 0xa4c50513 0x428896aa 0x00a04363 0x8c6386ae
00000000802001f0: 0x46c80306 0x05b78131 0x8d4d8000 0x05c16589
0000000080200200: 0x007395b6 0x10731200 0x00731805 0x90731200
0000000080200210: 0x16371405 0x25038020 0x0521a406 0x00868593
0000000080200220: 0xa4d62023 0x8082b3f5 0x00000073 0x48858082
0000000080200230: 0x46014581 0x47014681 0x48014781 0x00000073
0000000080200240: 0x11418082 0x26f3c606 0x27731420 0x27f31430
0000000080200250: 0x15371410 0x05138020 0x15b79fa5 0x85938020
0000000080200260: 0x06139145 0x232107a0 0x0001a001 0x14011173
0000000080200270: 0xf8410113 0xc20ec006 0xc616c412 0xca1ec81a
0000000080200280: 0xce76cc72 0xd27ed07a 0xd62ed42a 0xda36d832
0000000080200290: 0xde3edc3a 0xc2c6c0c2 0xc6a6c4a2 0xcacec8ca
00000000802002a0: 0xced6ccd2 0xd2ded0da 0xd6e6d4e2 0xdaeed8ea
00000000802002b0: 0x14002573 0x18e8dcaa 0x14051073 0x3751850a
00000000802002c0: 0x41924082 0x42b24222 0x43d24342 0x4ef24e62
00000000802002d0: 0x5f925f02 0x55b25522 0x56d25642 0x57f25762
00000000802002e0: 0x48964806 0x44b64426 0x49d64946 0x4af64a66
00000000802002f0: 0x5b965b06 0x5cb65c26 0x5dd65d46 0x00735166
0000000080200300: 0x11411020 0xc422c606 0x802015b7 0xa385a403
0000000080200310: 0x00c51613 0x00c40533 0x842316b7 0x00068693
0000000080200320: 0xa2a5ac23 0x00a6fe63 0x80201537 0x96750513
0000000080200330: 0x802015b7 0x91458593 0x0d500613 0xa001290d
0000000080200340: 0x45818522 0x852226c9 0x442240b2 0x80820141
0000000080200350: 0xce061101 0xca26cc22 0xc64ec84a 0x842ec452
0000000080200360: 0xcd9105d2 0x80201537 0x98750513 0x802015b7
0000000080200370: 0x91458593 0x0dd00613 0x2ed586a2 0x6585a001
0000000080200380: 0x8df115fd 0x1537cd91 0x05138020 0x15b791d5
0000000080200390: 0x85938020 0x86b29145 0x0e000613 0xa0012ec9
00000000802003a0: 0x01445593 0x04b399f1 0x408800b5 0x00157593
00000000802003b0: 0x1537e9a1 0x29038020 0x6585a385 0x173795ca
00000000802003c0: 0x07138423 0x2c230007 0x7e63a2b5 0x153700b7
00000000802003d0: 0x05138020 0x15b79675 0x85938020 0x06139145
00000000802003e0: 0x26710d50 0x89b2a001 0x854a6605 0x8a364581
00000000802003f0: 0x86d22e19 0x5513864e 0x052a00c9 0xc0880505
0000000080200400: 0x05328129 0x8e558209 0x00166593 0x66058029
0000000080200410: 0x8e611671 0xc10c8d51 0x446240f2 0x494244d2
0000000080200420: 0x4a2249b2 0x80826105 0xce061101 0xca26cc22
0000000080200430: 0xc64ec84a 0xc256c452 0x15b7c05a 0x85938020
0000000080200440: 0x41d0a4c5 0x6609c62d 0x4a50962e 0x1637c23d
0000000080200450: 0x06138020 0x6691a4c6 0x52d496b2 0x6699cea9
0000000080200460: 0x5a509636 0x1637ca39 0x06138020 0x66a1a4c6
0000000080200470: 0x42f496b2 0x66a9c6a9 0x4a709636 0x1637c239
0000000080200480: 0x06138020 0x66b1a4c6 0x52f496b2 0x66b9ce8d
0000000080200490: 0x5a709636 0x1537ca1d 0x05138020 0x15b79d55
00000000802004a0: 0x85938020 0x06139145 0x24d10fc0 0x4901a001
00000000802004b0: 0x4905a831 0x4909a821 0x490da811 0x4911a801
00000000802004c0: 0x4915a031 0x4919a021 0x491da011 0x00491613
00000000802004d0: 0x00d91693 0x00c6e9b3 0x660995ce 0x00c586b3
00000000802004e0: 0x0006a623 0x0006a423 0x0006a223 0x0006a023
00000000802004f0: 0xfe06ae23 0xfe06ac23 0xfe06aa23 0xfe06a823
0000000080200500: 0xfe06a623 0xfe06a423 0xfe06a223 0xfe06a023
0000000080200510: 0xfdc60a13 0x80201637 0xa3862b03 0x20239a2e
0000000080200520: 0x650500aa 0x15b7955a 0x84138423 0x2c230005
0000000080200530: 0x7e63a2a6 0x153700a4 0x05138020 0x15b79675
0000000080200540: 0x85938020 0x06139145 0x24150d50 0x6605a001
0000000080200550: 0x855a6a85 0x2a454581 0x80200537 0x00050493
0000000080200560: 0x0084fe63 0x84231537 0x00050413 0x855a46b9
0000000080200570: 0x862685a6 0x94d63bf1 0xfe84eae3 0x80201537
0000000080200580: 0xa4c50513 0x0905954e 0x01252023 0xc14c4585
0000000080200590: 0x01452423 0x01652623 0x446240f2 0x494244d2
00000000802005a0: 0x4a2249b2 0x4b024a92 0x80826105 0x01c9c537
00000000802005b0: 0x38050513 0x0001157d 0x8082fd75 0xc6061141
00000000802005c0: 0xc226c422 0x1537c04a 0x05138020 0x22459535
00000000802005d0: 0x01c9c537 0x38050413 0x80201937 0x802014b7
00000000802005e0: 0x04100513 0x45814885 0x46814601 0x47814701
00000000802005f0: 0x00734801 0x85220000 0x0001157d 0x2503fd75
0000000080200600: 0xa583a449 0x0521a484 0x341905a1 0xbfc934a9
0000000080200610: 0xc6061141 0xc226c422 0x1537c04a 0x05138020
0000000080200620: 0x22b193f5 0x01c9c537 0x38050413 0x80201937
0000000080200630: 0x802014b7 0x04200513 0x45814885 0x46814601
0000000080200640: 0x47814701 0x00734801 0x85220000 0x0001157d
0000000080200650: 0x2503fd75 0xa583a489 0x0521a444 0x3a4d05a1
0000000080200660: 0xbfc93add 0xc6061141 0x80201537 0xa3c50513
0000000080200670: 0x802115b7 0xacc58613 0x45818e09 0x15372069
0000000080200680: 0x05138020 0x20e59845 0x80200537 0x26c50513
0000000080200690: 0x10551073 0x3b494501 0x802015b7 0xa2a5ae23
00000000802006a0: 0x00052023 0x802015b7 0xa4a5a023 0x80200537
00000000802006b0: 0x5bc50513 0x15b73b95 0xa2238020 0x0537a4a5
00000000802006c0: 0x05138020 0x338d6105 0x802015b7 0xa4a5a423
00000000802006d0: 0x15373259 0x05138020 0x15b79a95 0x85938020
00000000802006e0: 0x06139145 0x206114b0 0xce09a001 0x86aa962a
00000000802006f0: 0x0005c703 0x87930585 0x80230016 0x86be00e6
0000000080200700: 0xfec798e3 0xca118082 0x86aa962a 0x00168713
0000000080200710: 0x00b68023 0x1be386ba 0x8082fec7 0x0005c603
0000000080200720: 0xce0186aa 0x872a0585 0x00c70023 0x0005c603
0000000080200730: 0x00170693 0x87360585 0x8023fa65 0x80820006
0000000080200740: 0x00054603 0x0505c205 0x0005c683 0x0ff67713
0000000080200750: 0x00d71763 0x00054603 0x05050585 0x7513f675
0000000080200760: 0xa0110ff6 0xc5834501 0x8d0d0005 0x711d8082
0000000080200770: 0xdc22de06 0xd84ada26 0xd452d64e 0xd05ad256
0000000080200780: 0xcc62ce5e 0xc86aca66 0x842ac66e 0xccc2cec6
0000000080200790: 0xc8bacabe 0xc4b2c6b6 0x00c8c2ae 0x0a13c42a
00000000802007a0: 0x09130250 0x4b290720 0xd5374aa5 0x0d13cccc
00000000802007b0: 0x0b93ccd5 0x0c130730 0x15370780 0x0c938020
00000000802007c0: 0xa0219c45 0x12050663 0x45030405 0x07630004
00000000802007d0: 0x02630145 0x3ca11205 0xbfc50405 0x00144503
00000000802007e0: 0x44630405 0x08e302a9 0x0593ff45 0x1be30640
00000000802007f0: 0x4522fcb5 0x00450593 0x2d83c42e 0xc8630005
0000000080200800: 0x45050a0d 0x0d6de463 0x0063a85d 0x1de30975
0000000080200810: 0x4522fb85 0x00450593 0x4104c42e 0x01c4d513
0000000080200820: 0x45039566 0x34210005 0x00449513 0x95668171
0000000080200830: 0x00054503 0x95133aed 0x81710084 0x45039566
0000000080200840: 0x32f50005 0x00c49513 0x95668171 0x00054503
0000000080200850: 0x95133af9 0x81710104 0x45039566 0x3ac10005
0000000080200860: 0x01449513 0x95668171 0x00054503 0x951332c9
0000000080200870: 0x81710184 0x45039566 0x3a550005 0x94e688bd
0000000080200880: 0x0004c503 0x0405326d 0x4522b789 0x00450593
0000000080200890: 0x4104c42e 0x0004c503 0xf20508e3 0x75130485
00000000802008a0: 0x32710ff5 0x0004c503 0xf9750485 0x0513bf31
00000000802008b0: 0x3ab502d0 0x41b00db3 0xe9634505 0x4505016d
00000000802008c0: 0x03650533 0x02add5b3 0xfebacce3 0xc9b384aa
00000000802008d0: 0x851302ad 0x75130309 0x3a910ff5 0x02998533
00000000802008e0: 0x40ad8db3 0x03a4b533 0xf1e3810d 0xbde9ff64
00000000802008f0: 0x02500513 0x50f23a2d 0x54d25462 0x59b25942
0000000080200900: 0x5a925a22 0x4bf25b02 0x4cd24c62 0x4db24d42
0000000080200910: 0x80826125 0x6e72656b 0x632e6c65 0x4e415000
0000000080200920: 0x203a4349 0x253a7325 0x75203a64 0x696c616e
0000000080200930: 0x64656e67 0x64617020 0x24207264 0x73000a78
0000000080200940: 0x74726174 0x20676e69 0x636f7270 0x20737365
0000000080200950: 0x73000a42 0x74726174 0x20676e69 0x636f7270
0000000080200960: 0x20737365 0x50000a41 0x43494e41 0x7325203a
0000000080200970: 0x3a64253a 0x74756f20 0x20666f20 0x6f6d656d
0000000080200980: 0x000a7972 0x50000a0a 0x43494e41 0x7325203a
0000000080200990: 0x3a64253a 0x616e7520 0x6e67696c 0x76206465
00000000802009a0: 0x72646461 0x0a782420 0x4e415000 0x203a4349
00000000802009b0: 0x253a7325 0x75203a64 0x6165726e 0x62616863
00000000802009c0: 0x000a656c 0x33323130 0x37363534 0x62613938
00000000802009d0: 0x66656463 0x4e415000 0x203a4349 0x253a7325
00000000802009e0: 0x6e203a64 0x7266206f 0x70206565 0x65636f72
00000000802009f0: 0x73207373 0x73746f6c 0x4150000a 0x3a43494e
0000000080200a00: 0x3a732520 0x203a6425 0x78656e75 0x74636570
0000000080200a10: 0x74206465 0x20706172 0x75616373 0x253d6573
0000000080200a20: 0x73202c78 0x6c617674 0x2c78253d 0x70657320
0000000080200a30: 0x78253d63 0x00000a0a 0x80267000 0x80200a4c
0000000080200a40: 0x80202a5c 0x80202a5c 0x80204a6c 0x00000000
0000000080200a50: 0x00000001 0x80230a88 0x80231000 0x00000000
0000000080200a60: 0x00000000 0x00000000 0x00000000 0x00000000
0000000080200a70: 0x00000000 0x00000000 0x00000000 0x00000000
0000000080200a80: 0x00000000 0x00000000 0x00000000 0x00000000
0000000080200a90: 0x00000000 0x00000000 0x00000000 0x00000000
0000000080200aa0: 0x00000000 0x00000000 0x00000000 0x00000000
0000000080200ab0: 0x00000000 0x00000000 0x00000000 0x00000000
0000000080200ac0: 0x00000000 0x00000000 0x00000000 0x00000000
0000000080200ad0: 0x00000000 0x00000000 0x00000000 0x00000000
0000000080200ae0: 0x00000000 0x00000000 0x00000000 0x00000000
0000000080200af0: 0x00000000 0x00000000 0x00000000 0x00000000
0000000080200b00: 0x00000000 0x00000000 0x00000000 0x00000000
0000000080200b10: 0x00000000 0x00000000 0x00000000 0x00000000
0000000080200b20: 0x00000000 0x00000000 0x00000000 0x00000000
0000000080200b30: 0x00000000 0x00000000 0x00000000 0x00000000
0000000080200b40: 0x00000000 0x00000000 0x00000000 0x00000000
0000000080200b50: 0x00000000 0x00000000 0x00000000 0x00000000
0000000080200b60: 0x00000000 0x00000000 0x00000000 0x00000000
0000000080200b70: 0x00000000 0x00000000 0x00000000 0x00000000
0000000080200b80: 0x00000000 0x00000000 0x00000000 0x00000000
0000000080200b90: 0x00000000 0x00000000 0x00000000 0x00000000
0000000080200ba0: 0x00000000 0x00000000 0x00000000 0x00000000
0000000080200bb0: 0x00000000 0x00000000 0x00000000 0x00000000
0000000080200bc0: 0x00000000 0x00000000 0x00000000 0x00000000
0000000080200bd0: 0x00000000 0x00000000 0x00000000 0x00000000
0000000080200be0: 0x00000000 0x00000000 0x00000000 0x00000000
0000000080200bf0: 0x00000000 0x00000000 0x00000000 0x00000000
0000000080200c00: 0x00000000 0x00000000 0x00000000 0x00000000
0000000080200c10: 0x00000000 0x00000000 0x00000000 0x00000000
0000000080200c20: 0x00000000 0x00000000 0x00000000 0x00000000
0000000080200c30: 0x00000000 0x00000000 0x00000000 0x00000000
0000000080200c40: 0x00000000 0x00000000 0x00000000 0x00000000
0000000080200c50: 0x00000000 0x00000000 0x00000000 0x00000000
0000000080200c60: 0x00000000 0x00000000 0x00000000 0x00000000
0000000080200c70: 0x00000000 0x00000000 0x00000000 0x00000000
0000000080200c80: 0x00000000 0x00000000 0x00000000 0x00000000
0000000080200c90: 0x00000000 0x00000000 0x00000000 0x00000000
0000000080200ca0: 0x00000000 0x00000000 0x00000000 0x00000000
0000000080200cb0: 0x00000000 0x00000000 0x00000000 0x00000000
0000000080200cc0: 0x00000000 0x00000000 0x00000000 0x00000000
0000000080200cd0: 0x00000000 0x00000000 0x00000000 0x00000000
0000000080200ce0: 0x00000000 0x00000000 0x00000000 0x00000000
0000000080200cf0: 0x00000000 0x00000000 0x00000000 0x00000000
0000000080200d00: 0x00000000 0x00000000 0x00000000 0x00000000
0000000080200d10: 0x00000000 0x00000000 0x00000000 0x00000000
0000000080200d20: 0x00000000 0x00000000 0x00000000 0x00000000
0000000080200d30: 0x00000000 0x00000000 0x00000000 0x00000000
0000000080200d40: 0x00000000 0x00000000 0x00000000 0x00000000
0000000080200d50: 0x00000000 0x00000000 0x00000000 0x00000000
0000000080200d60: 0x00000000 0x00000000 0x00000000 0x00000000
0000000080200d70: 0x00000000 0x00000000 0x00000000 0x00000000
0000000080200d80: 0x00000000 0x00000000 0x00000000 0x00000000
0000000080200d90: 0x00000000 0x00000000 0x00000000 0x00000000
0000000080200da0: 0x00000000 0x00000000 0x00000000 0x00000000
0000000080200db0: 0x00000000 0x00000000 0x00000000 0x00000000
0000000080200dc0: 0x00000000 0x00000000 0x00000000 0x00000000
0000000080200dd0: 0x00000000 0x00000000 0x00000000 0x00000000
0000000080200de0: 0x00000000 0x00000000 0x00000000 0x00000000
0000000080200df0: 0x00000000 0x00000000 0x00000000 0x00000000
0000000080200e00: 0x00000000 0x00000000 0x00000000 0x00000000
0000000080200e10: 0x00000000 0x00000000 0x00000000 0x00000000
0000000080200e20: 0x00000000 0x00000000 0x00000000 0x00000000
0000000080200e30: 0x00000000 0x00000000 0x00000000 0x00000000
0000000080200e40: 0x00000000 0x00000000 0x00000000 0x00000000
0000000080200e50: 0x00000000 0x00000000 0x00000000 0x00000000
0000000080200e60: 0x00000000 0x00000000 0x00000000 0x00000000
0000000080200e70: 0x00000000 0x00000000 0x00000000 0x00000000
0000000080200e80: 0x00000000 0x00000000 0x00000000 0x00000000
0000000080200e90: 0x00000000 0x00000000 0x00000000 0x00000000
0000000080200ea0: 0x00000000 0x00000000 0x00000000 0x00000000
0000000080200eb0: 0x00000000 0x00000000 0x00000000 0x00000000
0000000080200ec0: 0x00000000 0x00000000 0x00000000 0x00000000
0000000080200ed0: 0x00000000 0x00000000 0x00000000 0x00000000
0000000080200ee0: 0x00000000 0x00000000 0x00000000 0x00000000
0000000080200ef0: 0x00000000 0x00000000 0x00000000 0x00000000
0000000080200f00: 0x00000000 0x00000000 0x00000000 0x00000000
0000000080200f10: 0x00000000 0x00000000 0x00000000 0x00000000
0000000080200f20: 0x00000000 0x00000000 0x00000000 0x00000000
0000000080200f30: 0x00000000 0x00000000 0x00000000 0x00000000
0000000080200f40: 0x00000000 0x00000000 0x00000000 0x00000000
0000000080200f50: 0x00000000 0x00000000 0x00000000 0x00000000
0000000080200f60: 0x00000000 0x00000000 0x00000000 0x00000000
0000000080200f70: 0x00000000 0x00000000 0x00000000 0x00000000
0000000080200f80: 0x00000000 0x00000000 0x00000000 0x00000000
0000000080200f90: 0x00000000 0x00000000 0x00000000 0x00000000
0000000080200fa0: 0x00000000 0x00000000 0x00000000 0x00000000
0000000080200fb0: 0x00000000 0x00000000 0x00000000 0x00000000
0000000080200fc0: 0x00000000 0x00000000 0x00000000 0x00000000
0000000080200fd0: 0x00000000 0x00000000 0x00000000 0x00000000
0000000080200fe0: 0x00000000 0x00000000 0x00000000 0x00000000
0000000080200ff0: 0x00000000 0x00000000 0x00000000 0x00000000
보이는 메모리 덤프는 하나의 4K 페이지 데이터를 보여주고 있다.
(qemu) info mem
vaddr paddr size attr
-------- ---------------- -------- -------
80200000 0000000080200000 00001000 rwx--ad
80201000 0000000080201000 00001000 rwx----
80202000 0000000080202000 00001000 rwx--ad
80203000 0000000080203000 00001000 rwx----
80204000 0000000080204000 00001000 rwx--ad
80205000 0000000080205000 00001000 rwx----
80206000 0000000080206000 00001000 rwx--ad
80207000 0000000080207000 00029000 rwx----
80230000 0000000080230000 00001000 rwx--ad
80231000 0000000080231000 001cf000 rwx----
80400000 0000000080400000 00400000 rwx----
80800000 0000000080800000 00400000 rwx----
80c00000 0000000080c00000 00400000 rwx----
81000000 0000000081000000 00400000 rwx----
81400000 0000000081400000 00400000 rwx----
81800000 0000000081800000 00400000 rwx----
81c00000 0000000081c00000 00400000 rwx----
82000000 0000000082000000 00400000 rwx----
82400000 0000000082400000 00400000 rwx----
82800000 0000000082800000 00400000 rwx----
82c00000 0000000082c00000 00400000 rwx----
83000000 0000000083000000 00400000 rwx----
83400000 0000000083400000 00400000 rwx----
83800000 0000000083800000 00400000 rwx----
83c00000 0000000083c00000 00400000 rwx----
84000000 0000000084000000 00231000 rwx----
직접 메모리 덤프를 보는 대신, QEMU에는 현재 페이지 테이블 매핑 정보를 사람이 보기 좋게 출력하는 info mem
명령어도 있다.
r
: 읽기 가능w
: 쓰기 가능x
: 실행 가능a
: accessed, CPU가 페이지를 읽거나 실행함d
: dirty: CPU가 페이지에 기록함
조금 어려웠다...
'CS > OS' 카테고리의 다른 글
[1000줄 OS 구현하기] 유저 모드 (0) | 2025.03.11 |
---|---|
[1000줄 OS 구현하기] 애플리케이션 (0) | 2025.03.09 |
[1000줄 OS 구현하기] 프로세스 (0) | 2025.03.06 |
[1000줄 OS 구현하기] 메모리 할당 (0) | 2025.02.11 |
[1000줄 OS 구현하기] 예외 (0) | 2025.02.05 |