The Linux Memory Manager

책을 바탕으로 개념과 Linux 소스 코드를 함께 살펴보는 한국어 독립 학습 연재입니다.

14개 장 · 161편

1장 · 소스 읽기

  1. Linux Memory Management를 소스에서 읽는 순서

2장 · Physical memory

  1. struct page를 읽기 전에 주소와 수명을 구별합니다
  2. Compound page의 head와 tail은 같은 일을 하지 않습니다
  3. struct slab는 struct page와 어떻게 같은 메모리를 씁니까
  4. Page flag를 읽을 때 folio와 tail 규칙을 함께 봅니다
  5. PFN이 유효하다는 말은 RAM을 쓸 수 있다는 뜻이 아닙니다
  6. NUMA node와 zone은 allocation 후보를 어떻게 나눕니까
  7. Lowmem reserve는 비어 있는 page를 따로 잠가 두는 기능이 아닙니다
  8. MOVABLE pageblock이라고 지금 모든 page를 옮길 수 있는 것은 아닙니다
  9. GFP mask는 memory의 종류보다 allocation의 허용 행동을 정합니다
  10. Buddy의 큰 block과 PCP의 빠른 재사용은 어떻게 공존합니까
  11. alloc_pages는 free list를 보기 전에 무엇을 결정합니까
  12. Watermark를 통과한 page allocation도 다시 실패할 수 있습니다
  13. Buddy fallback은 언제 pageblock의 소속을 바꿉니까
  14. Page 해제는 마지막 참조와 buddy 합병 사이의 여러 단계입니다
  15. Page flag helper의 이름보다 실제 제공 조합을 먼저 봅니다
  16. alloc_pages와 folio_alloc은 같은 memory를 어떻게 다르게 요청합니까
  17. Bulk page allocation의 반환값은 새 page 수와 같지 않습니다

3장 · Virtual memory

  1. virtual address를 page table로 바꾸는 방법
  2. PTE의 권한과 software state를 읽는 법
  3. page table을 읽고 고칠 때 지켜야 할 경계
  4. kernel pointer마다 주소 변환 규칙이 다릅니다
  5. direct map은 자기 table을 어디에 만드나요
  6. direct map의 경계를 leaf와 table로 나누기
  7. vmalloc은 빈 주소 구간부터 확보합니다
  8. vmalloc의 backing page와 실패 정리
  9. x86-64 kernel 주소의 경계를 계산하는 법
  10. vmalloc free tree에서 주소 하나를 꺼내는 과정
  11. vmalloc mapping은 실패한 뒤에도 흔적을 남깁니다

4장 · Process memory

  1. mmap 성공과 RAM 확보는 다른 약속입니다
  2. mm_struct에는 두 개의 수명이 있습니다
  3. process마다 PGD를 가져도 kernel mapping은 공유합니다
  4. 주소 공간의 lock과 policy를 나누어 읽기
  5. VMA는 주소 범위에 붙은 동작 계약입니다
  6. VMA 검색 결과가 주소를 포함하지 않을 때
  7. file mapping은 page cache와 어떻게 연결되나요
  8. RSS는 process가 소유한 RAM의 총합이 아닙니다
  9. mm_struct의 field와 실패 경로를 함께 읽기
  10. mmap_lock을 놓은 뒤에는 무엇을 다시 확인해야 할까요
  11. VMA 삽입은 pointer 하나를 잇는 작업이 아닙니다
  12. fault가 돌아왔을 때 mmap lock은 누구에게 있나요
  13. procfs와 fault 진단이 VMA를 잠깐 붙잡는 이유
  14. 같은 mm을 보고도 reclaim과 policy 변경의 lock이 다른 이유

5장 · Memory mapping

  1. brk가 움직이는 두 경계: heap의 byte 끝과 VMA의 page 끝
  2. mmap flags를 읽을 때 나누어야 할 세 가지 약속
  3. mmap이 VMA를 연결하기 전에 확인하는 것들
  4. mmap 주소 선택은 빈 주소가 아니라 충분한 gap을 찾는 일입니다
  5. munmap은 VMA 경계를 자르고 translation의 수명을 끝냅니다
  6. 서로 붙어 있는 VMA가 합쳐지지 않는 이유
  7. VMA 경계를 바꿀 때 주소 tree만 고쳐서는 안 됩니다
  8. VMA split은 복사한 struct의 소유권을 다시 만드는 작업입니다
  9. 고전 VMA 조정 코드를 읽는 법: 범위와 object 수명을 함께 봅니다

6장 · Page fault

  1. kernel mode의 page fault도 사용자 주소에서 시작할 수 있습니다
  2. page fault의 반환값에는 lock 소유권도 들어 있습니다
  3. 비어 있는 PTE와 present가 아닌 PTE는 같은 상태가 아닙니다
  4. 처음 읽은 anonymous memory와 처음 쓴 memory의 비용이 다릅니다
  5. warm page cache에서도 mmap read fault가 필요한 이유
  6. private write는 복사하고 shared write는 backing의 승인을 받습니다
  7. CoW fault에서 복사하지 않아도 되는 순간
  8. stack fault는 backing allocation보다 먼저 주소 공간을 넓힙니다
  9. present PTE가 있어도 vm_normal_page는 NULL일 수 있습니다

7장 · Reverse mapping

  1. physical folio에서 process 주소를 찾는 rmap의 세 가지 객체
  2. 첫 anonymous fault에서 anon_vma를 준비하고 이웃 객체를 재사용하는 방법
  3. fork는 anonymous page보다 rmap 관계를 먼저 복제합니다
  4. mremap 뒤에도 anonymous folio의 index가 유지되는 이유
  5. rmap은 후보를 찾고 page-table walk가 실제 mapping을 증명합니다
  6. PTE를 지운 뒤에도 folio를 바로 free하면 안 되는 이유
  7. zap이 PTE의 dirty와 young bit를 버리지 않는 이유
  8. 빈 PTE와 free할 수 있는 page-table page는 다릅니다
  9. TLB shootdown은 모든 CPU에 무조건 같은 flush를 시키는 작업이 아닙니다

8장 · User memory

  1. copy_from_user의 실패는 왜 복사하지 못한 byte 수로 돌아오나요
  2. GUP pin은 user address가 아니라 physical object의 수명을 붙잡습니다
  3. GUP wrapper를 고를 때는 lock을 놓을 수 있는지 먼저 확인합니다
  4. GUP가 일부 page만 반환했을 때 caller에게 남는 책임
  5. GUP의 page-table walk는 permission과 CoW 상태를 함께 검사합니다
  6. fast GUP는 먼저 pin하고 나중에 관찰이 맞았는지 확인합니다
  7. prefault는 pin이나 residency 보장과 다릅니다
  8. mlock, mprotect, mremap은 mapping의 서로 다른 속성을 바꿉니다
  9. madvise는 성능 hint일 수도 있고 data를 버리는 명령일 수도 있습니다

9장 · Page cache

  1. 파일을 두 번 열어도 page cache가 두 벌 생기지 않는 이유
  2. XArray는 파일의 드문 index와 큰 folio를 어떻게 담을까요?
  3. read가 요청한 byte보다 적게 반환할 때 kernel이 한 일
  4. file-backed fault가 cache hit 뒤에도 다시 시작하는 이유
  5. page cache batch는 무엇을 돌려주고 무엇을 건너뛸까요?
  6. folio 하나를 찾는 일과 내용을 읽어 오는 일 사이
  7. Readahead는 다음 읽기를 어디까지 예상할까요?
  8. Readahead가 filesystem에 folio를 넘길 때 참조는 누가 갖나요?
  9. Fault-around는 disk를 읽지 않고도 fault를 줄입니다
  10. Truncate는 cache entry만 지우는 작업이 아닙니다
  11. Clean page도 drop_caches 뒤에 남을 수 있습니다
  12. Buffer head가 folio 안의 block을 추적하는 방법
  13. Folio를 기다린 뒤에도 lock을 얻지 못할 수 있습니다
  14. Readahead는 marker와 cache history로 읽기 흐름을 다시 찾습니다
  15. Page cache에서 지운 folio는 언제 실제로 해제될까요?
  16. 파일 offset 하나가 여러 VMA의 PTE를 지울 때
  17. Block-device cache는 파일의 page cache와 무엇이 다를까요?

10장 · Writeback

  1. Dirty folio를 찾으려면 inode도 dirty여야 합니다
  2. MAP_SHARED에 한 번 쓴 뒤 다음 write가 fault를 내지 않는 이유
  3. Buffered write는 복사한 byte를 왜 다시 돌려놓을까요?
  4. fsync와 fdatasync는 무엇을 기다리며 어디까지 저장할까요?
  5. Dirty를 지운 folio가 아직 저장되지 않은 이유
  6. Writeback 요청은 worker에 어떻게 전달될까요?
  7. Flusher가 오래된 inode부터 쓰면서도 sync를 먼저 처리하는 방법
  8. Writeback을 마친 inode는 어느 목록으로 돌아갈까요?
  9. Writeback을 기다렸는데도 error를 따로 확인해야 하는 이유
  10. 빠르던 buffered write가 잠드는 것은 누가 결정할까요?
  11. Writeback bandwidth는 제출량이 아니라 완료량에서 추정합니다
  12. Dirty limit가 있는데도 별도의 setpoint가 필요한 이유
  13. Writer 수를 세지 않고 task별 dirty rate를 맞추는 방법
  14. Dirty throttling은 얼마나 쉬게 하고 언제 다시 쓰게 할까요?
  15. Writeback iterator는 오류가 나도 다음 folio를 찾을 수 있습니다
  16. Superblock sync는 work 완료와 I/O 완료를 따로 기다립니다
  17. Flusher의 oldest-first는 목록 방향과 superblock 묶음을 함께 봅니다
  18. Dirty throttling의 반환 조건을 따라가면 writer가 잠드는 이유가 보입니다

11장 · Reclaim

  1. Free page가 있는데도 할당이 느려지는 이유: allocator slow path
  2. Classic LRU는 마지막 접근 시각 대신 사용 흔적을 모읍니다
  3. Direct reclaim: 할당한 task가 회수 비용을 부담할 때
  4. kswapd가 깨어나고 다시 잠들기까지
  5. Reclaim은 무엇을 기억할까요: scan_control과 working set
  6. Swappiness는 RAM 사용 비율이 아니라 scan 압력의 입력입니다
  7. 32장씩 scan하면 비율이 어긋납니다: lruvec batch의 보정
  8. LRU에서 folio를 꺼내도 아직 free가 아닙니다
  9. Inactive folio가 allocator로 돌아가기까지
  10. 사용 흔적·writeback·cache 제거는 서로 다른 검사입니다
  11. Reclaim도 기다려야 할 때가 있습니다
  12. Folio batch는 data가 아니라 LRU 작업을 모읍니다
  13. Activate·rotate·deactivate·lazy-free는 같은 이동이 아닙니다
  14. LRU batch drain과 PCP drain을 구분해 읽기
  15. LRU 복귀와 마지막 put: list에서 빠지는 세 가지 이유
  16. Node reclaim은 왜 같은 folio를 더 빨리 돌기보다 기다릴까요
  17. v6.18 folio reclaim: swap 준비부터 demotion과 최종 free까지

12장 · Swap

  1. Swap entry가 있는데 page는 왜 RAM에 남아 있을까요?
  2. Present PTE를 swap entry로 바꿀 때 보존해야 하는 것
  3. Swap-out의 네 시점: 예약, PTE 교체, I/O, RAM 반환
  4. Swap fault는 내용을 찾은 뒤에도 끝나지 않습니다
  5. Swap cache miss에서 같은 slot을 두 번 읽지 않는 방법
  6. Swap cluster readahead는 주소가 아니라 slot 순서로 읽습니다
  7. VMA readahead는 process가 걷는 주소를 따라갑니다

13장 · OOM

  1. OOM은 RAM 사용률 100%보다 allocation의 제약에서 시작합니다
  2. OOM handler가 성공했다고 새 process를 죽인 것은 아닙니다
  3. OOM 점수보다 먼저 볼 것: 후보 범위와 ownership
  4. Victim을 골랐는데 왜 다른 thread group에도 SIGKILL을 보낼까요?
  5. OOM reaper는 왜 잠깐 기다린 뒤 trylock할까요?
  6. OOM reaper는 어느 VMA를 비울 수 있을까요?

14장 · 관찰과 활용

  1. Free memory가 적어도 allocation이 가능한 이유
  2. RSS를 더하면 physical memory 사용량이 되는가요
  3. mmap()에서 mapping의 수명과 file의 수명 구분하기
  4. OOM report에서 먼저 확인할 것은 실패한 allocation입니다
  5. OOM report의 memory 통계로 회수할 수 없는 부분 찾기
  6. Memory를 볼 때 /proc 파일을 고르는 기준
  7. Virtual address에서 PFN을 조사할 때 필요한 두 index
  8. VM tunable을 바꾸기 전에 allocation의 어느 제약인지 구분하기
  9. Dirty threshold와 writeback 주기를 구분해서 읽기
  10. Shared memory를 만들었다고 IPC가 완성되지는 않습니다
  11. mmap() 실습: CoW, truncate, fixed address를 따로 확인합니다
  12. System V shared memory 실습: segment ID와 request/reply protocol
  13. POSIX shared memory 실습: 이름 공개부터 마지막 munmap()까지
  14. memfd 실습: SCM_RIGHTS로 전달하고 semaphore로 교환합니다
  15. OOM 통계의 단위를 맞추어 읽기
  16. VmFlags의 rd와 mr는 같은 권한이 아닙니다
  17. zoneinfo와 buddyinfo의 숫자를 같은 단위로 읽기