1장 · 소스 읽기
2장 · Physical memory
- struct page를 읽기 전에 주소와 수명을 구별합니다
- Compound page의 head와 tail은 같은 일을 하지 않습니다
- struct slab는 struct page와 어떻게 같은 메모리를 씁니까
- Page flag를 읽을 때 folio와 tail 규칙을 함께 봅니다
- PFN이 유효하다는 말은 RAM을 쓸 수 있다는 뜻이 아닙니다
- NUMA node와 zone은 allocation 후보를 어떻게 나눕니까
- Lowmem reserve는 비어 있는 page를 따로 잠가 두는 기능이 아닙니다
- MOVABLE pageblock이라고 지금 모든 page를 옮길 수 있는 것은 아닙니다
- GFP mask는 memory의 종류보다 allocation의 허용 행동을 정합니다
- Buddy의 큰 block과 PCP의 빠른 재사용은 어떻게 공존합니까
- alloc_pages는 free list를 보기 전에 무엇을 결정합니까
- Watermark를 통과한 page allocation도 다시 실패할 수 있습니다
- Buddy fallback은 언제 pageblock의 소속을 바꿉니까
- Page 해제는 마지막 참조와 buddy 합병 사이의 여러 단계입니다
- Page flag helper의 이름보다 실제 제공 조합을 먼저 봅니다
- alloc_pages와 folio_alloc은 같은 memory를 어떻게 다르게 요청합니까
- Bulk page allocation의 반환값은 새 page 수와 같지 않습니다
3장 · Virtual memory
- virtual address를 page table로 바꾸는 방법
- PTE의 권한과 software state를 읽는 법
- page table을 읽고 고칠 때 지켜야 할 경계
- kernel pointer마다 주소 변환 규칙이 다릅니다
- direct map은 자기 table을 어디에 만드나요
- direct map의 경계를 leaf와 table로 나누기
- vmalloc은 빈 주소 구간부터 확보합니다
- vmalloc의 backing page와 실패 정리
- x86-64 kernel 주소의 경계를 계산하는 법
- vmalloc free tree에서 주소 하나를 꺼내는 과정
- vmalloc mapping은 실패한 뒤에도 흔적을 남깁니다
4장 · Process memory
- mmap 성공과 RAM 확보는 다른 약속입니다
- mm_struct에는 두 개의 수명이 있습니다
- process마다 PGD를 가져도 kernel mapping은 공유합니다
- 주소 공간의 lock과 policy를 나누어 읽기
- VMA는 주소 범위에 붙은 동작 계약입니다
- VMA 검색 결과가 주소를 포함하지 않을 때
- file mapping은 page cache와 어떻게 연결되나요
- RSS는 process가 소유한 RAM의 총합이 아닙니다
- mm_struct의 field와 실패 경로를 함께 읽기
- mmap_lock을 놓은 뒤에는 무엇을 다시 확인해야 할까요
- VMA 삽입은 pointer 하나를 잇는 작업이 아닙니다
- fault가 돌아왔을 때 mmap lock은 누구에게 있나요
- procfs와 fault 진단이 VMA를 잠깐 붙잡는 이유
- 같은 mm을 보고도 reclaim과 policy 변경의 lock이 다른 이유
5장 · Memory mapping
- brk가 움직이는 두 경계: heap의 byte 끝과 VMA의 page 끝
- mmap flags를 읽을 때 나누어야 할 세 가지 약속
- mmap이 VMA를 연결하기 전에 확인하는 것들
- mmap 주소 선택은 빈 주소가 아니라 충분한 gap을 찾는 일입니다
- munmap은 VMA 경계를 자르고 translation의 수명을 끝냅니다
- 서로 붙어 있는 VMA가 합쳐지지 않는 이유
- VMA 경계를 바꿀 때 주소 tree만 고쳐서는 안 됩니다
- VMA split은 복사한 struct의 소유권을 다시 만드는 작업입니다
- 고전 VMA 조정 코드를 읽는 법: 범위와 object 수명을 함께 봅니다
6장 · Page fault
- kernel mode의 page fault도 사용자 주소에서 시작할 수 있습니다
- page fault의 반환값에는 lock 소유권도 들어 있습니다
- 비어 있는 PTE와 present가 아닌 PTE는 같은 상태가 아닙니다
- 처음 읽은 anonymous memory와 처음 쓴 memory의 비용이 다릅니다
- warm page cache에서도 mmap read fault가 필요한 이유
- private write는 복사하고 shared write는 backing의 승인을 받습니다
- CoW fault에서 복사하지 않아도 되는 순간
- stack fault는 backing allocation보다 먼저 주소 공간을 넓힙니다
- present PTE가 있어도 vm_normal_page는 NULL일 수 있습니다
7장 · Reverse mapping
- physical folio에서 process 주소를 찾는 rmap의 세 가지 객체
- 첫 anonymous fault에서 anon_vma를 준비하고 이웃 객체를 재사용하는 방법
- fork는 anonymous page보다 rmap 관계를 먼저 복제합니다
- mremap 뒤에도 anonymous folio의 index가 유지되는 이유
- rmap은 후보를 찾고 page-table walk가 실제 mapping을 증명합니다
- PTE를 지운 뒤에도 folio를 바로 free하면 안 되는 이유
- zap이 PTE의 dirty와 young bit를 버리지 않는 이유
- 빈 PTE와 free할 수 있는 page-table page는 다릅니다
- TLB shootdown은 모든 CPU에 무조건 같은 flush를 시키는 작업이 아닙니다
8장 · User memory
- copy_from_user의 실패는 왜 복사하지 못한 byte 수로 돌아오나요
- GUP pin은 user address가 아니라 physical object의 수명을 붙잡습니다
- GUP wrapper를 고를 때는 lock을 놓을 수 있는지 먼저 확인합니다
- GUP가 일부 page만 반환했을 때 caller에게 남는 책임
- GUP의 page-table walk는 permission과 CoW 상태를 함께 검사합니다
- fast GUP는 먼저 pin하고 나중에 관찰이 맞았는지 확인합니다
- prefault는 pin이나 residency 보장과 다릅니다
- mlock, mprotect, mremap은 mapping의 서로 다른 속성을 바꿉니다
- madvise는 성능 hint일 수도 있고 data를 버리는 명령일 수도 있습니다
9장 · Page cache
- 파일을 두 번 열어도 page cache가 두 벌 생기지 않는 이유
- XArray는 파일의 드문 index와 큰 folio를 어떻게 담을까요?
- read가 요청한 byte보다 적게 반환할 때 kernel이 한 일
- file-backed fault가 cache hit 뒤에도 다시 시작하는 이유
- page cache batch는 무엇을 돌려주고 무엇을 건너뛸까요?
- folio 하나를 찾는 일과 내용을 읽어 오는 일 사이
- Readahead는 다음 읽기를 어디까지 예상할까요?
- Readahead가 filesystem에 folio를 넘길 때 참조는 누가 갖나요?
- Fault-around는 disk를 읽지 않고도 fault를 줄입니다
- Truncate는 cache entry만 지우는 작업이 아닙니다
- Clean page도 drop_caches 뒤에 남을 수 있습니다
- Buffer head가 folio 안의 block을 추적하는 방법
- Folio를 기다린 뒤에도 lock을 얻지 못할 수 있습니다
- Readahead는 marker와 cache history로 읽기 흐름을 다시 찾습니다
- Page cache에서 지운 folio는 언제 실제로 해제될까요?
- 파일 offset 하나가 여러 VMA의 PTE를 지울 때
- Block-device cache는 파일의 page cache와 무엇이 다를까요?
10장 · Writeback
- Dirty folio를 찾으려면 inode도 dirty여야 합니다
- MAP_SHARED에 한 번 쓴 뒤 다음 write가 fault를 내지 않는 이유
- Buffered write는 복사한 byte를 왜 다시 돌려놓을까요?
- fsync와 fdatasync는 무엇을 기다리며 어디까지 저장할까요?
- Dirty를 지운 folio가 아직 저장되지 않은 이유
- Writeback 요청은 worker에 어떻게 전달될까요?
- Flusher가 오래된 inode부터 쓰면서도 sync를 먼저 처리하는 방법
- Writeback을 마친 inode는 어느 목록으로 돌아갈까요?
- Writeback을 기다렸는데도 error를 따로 확인해야 하는 이유
- 빠르던 buffered write가 잠드는 것은 누가 결정할까요?
- Writeback bandwidth는 제출량이 아니라 완료량에서 추정합니다
- Dirty limit가 있는데도 별도의 setpoint가 필요한 이유
- Writer 수를 세지 않고 task별 dirty rate를 맞추는 방법
- Dirty throttling은 얼마나 쉬게 하고 언제 다시 쓰게 할까요?
- Writeback iterator는 오류가 나도 다음 folio를 찾을 수 있습니다
- Superblock sync는 work 완료와 I/O 완료를 따로 기다립니다
- Flusher의 oldest-first는 목록 방향과 superblock 묶음을 함께 봅니다
- Dirty throttling의 반환 조건을 따라가면 writer가 잠드는 이유가 보입니다
11장 · Reclaim
- Free page가 있는데도 할당이 느려지는 이유: allocator slow path
- Classic LRU는 마지막 접근 시각 대신 사용 흔적을 모읍니다
- Direct reclaim: 할당한 task가 회수 비용을 부담할 때
- kswapd가 깨어나고 다시 잠들기까지
- Reclaim은 무엇을 기억할까요: scan_control과 working set
- Swappiness는 RAM 사용 비율이 아니라 scan 압력의 입력입니다
- 32장씩 scan하면 비율이 어긋납니다: lruvec batch의 보정
- LRU에서 folio를 꺼내도 아직 free가 아닙니다
- Inactive folio가 allocator로 돌아가기까지
- 사용 흔적·writeback·cache 제거는 서로 다른 검사입니다
- Reclaim도 기다려야 할 때가 있습니다
- Folio batch는 data가 아니라 LRU 작업을 모읍니다
- Activate·rotate·deactivate·lazy-free는 같은 이동이 아닙니다
- LRU batch drain과 PCP drain을 구분해 읽기
- LRU 복귀와 마지막 put: list에서 빠지는 세 가지 이유
- Node reclaim은 왜 같은 folio를 더 빨리 돌기보다 기다릴까요
- v6.18 folio reclaim: swap 준비부터 demotion과 최종 free까지
12장 · Swap
13장 · OOM
14장 · 관찰과 활용
- Free memory가 적어도 allocation이 가능한 이유
- RSS를 더하면 physical memory 사용량이 되는가요
- mmap()에서 mapping의 수명과 file의 수명 구분하기
- OOM report에서 먼저 확인할 것은 실패한 allocation입니다
- OOM report의 memory 통계로 회수할 수 없는 부분 찾기
- Memory를 볼 때 /proc 파일을 고르는 기준
- Virtual address에서 PFN을 조사할 때 필요한 두 index
- VM tunable을 바꾸기 전에 allocation의 어느 제약인지 구분하기
- Dirty threshold와 writeback 주기를 구분해서 읽기
- Shared memory를 만들었다고 IPC가 완성되지는 않습니다
- mmap() 실습: CoW, truncate, fixed address를 따로 확인합니다
- System V shared memory 실습: segment ID와 request/reply protocol
- POSIX shared memory 실습: 이름 공개부터 마지막 munmap()까지
- memfd 실습: SCM_RIGHTS로 전달하고 semaphore로 교환합니다
- OOM 통계의 단위를 맞추어 읽기
- VmFlags의 rd와 mr는 같은 권한이 아닙니다
- zoneinfo와 buddyinfo의 숫자를 같은 단위로 읽기