리눅스에서 페이지 테이블이 어떻게 구성되어 있는지 알아보자.
환경
리눅스 커널 5.15 버전, x86_64 기준
🌵 페이지 테이블 구조
테이블 매핑 방식은 4가지가 존재한다.
- 직접 매핑
- 연관 매핑
- 집합-연관 매핑
- 역매핑
- 해시형 테이블 구조
그중, 리눅스는 직접 매핑방식 중, 계층적 페이지 테이블을 사용한다.
계층적 페이지 테이블은 아래 그림을 보면 직관적으로 이해 할 수 있다.
64bit 를 나누어서, 각각을 offset 으로 사용하는 방식이다.
리눅스에서는 디폴트로 다음과 같이 4단계로 페이지 테이블을 구성한다.
PGD (Page Global Directory)
PUD (Page Upper Directory)
PMD (Page Middle Directory)
PTE (Page Table Entry)
pgtable_64_types.h
직접 코드를 보며 이해해보자.
https://github.com/torvalds/linux/blob/v5.15/arch/x86/include/asm/pgtable_64_types.h
의 코드를 일부 가져왔다.
#define PTRS_PER_PGD 512
#define PTRS_PER_PUD 512
#define PTRS_PER_PMD 512
#define PTRS_PER_PTE 512
위의 값을 봤을때, 각각의 테이블은 512개의 엔트리를 가지는 것을 알 수 있다.
2^9 = 512 이므로, 각각 9bit를 차지한다는 점을 알 수 있다.
리눅스는 기본적으로 4kb 페이지사이즈를 가지므로 (=12bit offset) 위와 같은 memory bit 구조를 가지게 된다.
memory.c
https://github.com/torvalds/linux/blob/v5.15/mm/memory.c
에서 follow_invalidate_pte 함수의 코드를 일부발췌 했다.
pgd_t *pgd; //pgd offset
pud_t *pud; //pud offset
pmd_t *pmd; //pmd offset
pte_t *ptep; //pte offset
pgd = pgd_offset(mm, address);
pud = pud_offset(pgd, address);
pmd = pmd_offset(pud, address);
ptep = pte_offset_map_lock(mm, pmd, address, ptlp);
코드를 통해 리눅스 커널이 실제로 페이지 테이블을 계층적으로 탐색한다는 점을 알게되었다.
Reference
https://velog.io/@lcy960729/%ED%8E%98%EC%9D%B4%EC%A7%80-%ED%85%8C%EC%9D%B4%EB%B8%94%EC%9D%98-%EA%B5%AC%EC%A1%B0-%EA%B3%84%EC%B8%B5%EC%A0%81-%ED%8E%98%EC%9D%B4%EC%A7%95
https://github.com/torvalds/linux/blob/v5.15/arch/x86/include/asm/pgtable_64_types.h
https://github.com/torvalds/linux/blob/v5.15/mm/memory.c
'CS > Linux' 카테고리의 다른 글
[Linux] recv()는 어떻게 잠들고 깨어날까? (0) | 2025.05.23 |
---|---|
[Linux] 네트워크 커널 스택: 리눅스 커널 네트워크 패킷 수신 여정 #3 (0) | 2025.05.22 |
[Linux] Ring Buffer 에서 NAPI: 리눅스 커널 네트워크 패킷 수신 여정 #2 (0) | 2025.05.21 |
[Linux] NIC에서 링 버퍼까지: 리눅스 커널 네트워크 패킷 수신 여정 #1 (0) | 2025.05.20 |
시스템 콜과 표준 라이브러리 관계 파헤치기: glibc는 어떻게 시스템 콜을 호출할까? (0) | 2025.05.09 |