목차
감수자의 글 ... xvii
머리말 ... xix
집필 후기 ... xxi
PART Ⅰ <B><FONT color ... #0000
   Chapter 1 커널에 대한 소개 그리고 2.6과 3.2의 차이 ... 2
      1.1. 커널의 탄생과 역할 그리고 내부 구조 ... 2
        1.1.1 리누스에 의해 탄생한 리눅스 ... 2
        1.1.2 다양한 서브시스템이 모여 동작하는 모노리딕 커널 ... 3
        1.1.3 전 세계에서 가장 유명한 범용 운영체제 ... 5
      1.2. 커널 2.6과 3.2의 차이 ... 6
   Chapter 2 커널 빌딩 시스템 ... 8
      2.1. 커널 초기화 ... 8
      2.2. 커널 설정 ... 9
      2.3. 커널 빌딩 ... 11
      2.4. 커널 설치 ... 19
   Chapter 3 ARM 프로세서 알아보기 ... 21
      3.1. 프로세서 개요와 특징 ... 21
      3.2. 프로세서 아키텍처와 코어 ... 22
      3.3. 프로세서 명명법 ... 23
      3.4. 프로세서 내부 구조 ... 24
      3.5. 프로세서 모드와 레지스터 ... 26
      3.6. 프로세서 익셉션 ... 28
      3.7. 하드웨어 확장 기능 ... 30
        3.7.1 캐시 ... 30
        3.7.2 메모리 관리 장치 ... 31
        3.7.3 코프로세서 ... 31
   Chapter 4 분석 환경 구축하기 ... 32
      4.1. 리눅스 커널 소스 다운로드하여 설치하기 ... 32
        4.1.1 커널 소스 다운로드하기 ... 32
        4.1.2 소스 설치하기 ... 34
      4.2. ctags+cscope 설치하기 ... 35
        4.2.1 ctags로 소스 코드 태그 만들기 ... 35
        4.2.2 cscope 태그 데이터베이스 만들기 ... 37
      4.3. vim 플러그인 다운로드 및 환경설정 ... 38
        4.3.1 vim 플러그인 다운로드하기 ... 39
        4.3.2 vim+plugin 환경구성 ... 43
        4.3.3 vim 환경설정하기 ... 44
      4.4. 소스 분석 환경 툴 둘러보기 ... 47
PART Ⅱ 커널의 시작 - start_kernel은 어떻게 호출될까?
   Chapter 5 커널 압축 해제 준비하기 ... 56
      5.1. 부트로더에 이어 첫 스타트 끊기 - start 레이블 ... 57
      5.2. BSS 영역 초기화하기 - not_relocated 레이블 ... 59
      5.3. 캐시 활성화하기 - cache_on 레이블 ... 62
      5.4. 페이지 디렉터리 엔트리 초기화하기 - __setup_mmu 레이블 ... 65
      5.5. I-Cache 활성화 및 캐시 정책 적용하기 - __common_mmu_cache_on 레이블 ... 69
   Chapter 6 압축된 커널 이미지인 zImage로부터 커널 이미지 복원하기 ... 70
      6.1. 덮어쓰지 않게 커널 압축 풀기 - wont_overwrite, decompress_kernel 레이블 ... 71
      6.2. 압축 해제된 커널 호출하기 - call_kernel 레이블 ... 72
      6.3. 캐시클린 및 플러시 - cache_clean_flush 레이블 ... 73
      6.4. 캐시 비활성화하기 - cache_off 레이블 ... 75
   Chapter 7 start_kernel() 호출하기 ... 76
      7.1. 초기화 조망하기 - stext 레이블 ... 76
      7.2. 프로세서 정보 찾기 - __look_processor_type ... 81
        7.2.1 __lookup_processor_type 레이블 ... 81
        7.2.2 __proc_info_begin과 __proc_info_end에 저장된 정보 ... 83
        7.2.3 MMU 비활성화 상태에서 가상 주소를 물리 주소로 변경하기 ... 85
        7.2.4 proc_info_list 구조체를 찾아 프로세서 정보 비교하기 ... 87
      7.3. 내 머신 타입 찾기 - __lookup_machine_type ... 88
        7.3.1 __lookup_machine_type 레이블 ... 88
        7.3.2 __arch_info_begin과 __arch_info_end에 저장된 machine_desc 정보와 접근 방법 ... 90
        7.3.3 machine_desc 구조체를 찾아 머신 정보 비교하기 ... 91
      7.4. 부트로더에서 온 atags - __vet_atags 레이블 ... 92
      7.5. 가상 메모리를 사용하기 위해 기초 공사하기 - __create_page_table 레이블 ... 95
      7.6. 코어를 설정하자 - v6_setup 레이블 ... 101
      7.7. MMU를 켜고 가상 주소 사용하기 - __enable_mmu/__turn_mmu_on 레이블 ... 102
      7.8. start_kernel로 점프 - __mmap_switched 레이블 ... 107
PART Ⅲ 커널의 실행 - 커널의 시작과 끝은 어디인가?
   Chapter 8 smp_setup_processor_id()∼lock_kernel() ... 112
      8.1. smp_setup_processor_id(), lockdep_init(), debug_objects_early_init() ... 113
        8.1.1 smp_setup_processor_id() ... 113
        8.1.2 lockdep_init() ... 113
        8.1.3 debug_objects_early_init() ... 115
      8.2. 스택 오버플로우 감지하기 - boot_init_stack_canary() ... 117
      8.3. 프로세스를 그룹화하는 방법을 제공하는 cgroup 초기화하기 - cgroup_init_early() ... 118
        8.3.1 cgroupfs_root와 cgroup의 관계 초기화하기 - init_cgroup_root() ... 123
        8.3.2 서브시스템 초기화하기 - cgroup_init_subsys() ... 123
      8.4. IRQ 비활성화하기 - local_irq_disable() ... 125
      8.5. early_boot_irqs_off(), early_init_irq_lock_class() ... 125
      8.6. 빅 커널 락 - lock_kernel() ... 127
   Chapter 9 클럭 이벤트에 대한 핸들러 등록하기 ... 134
      9.1. 함수의 선언과 정의 - tick_init() ... 134
      9.2. 이벤트 처리 핸들러 등록하기 - clockevents_register_notifier() ... 136
        9.2.1 clockevents_lock에 대한 스핀 락 걸기 ... 137
        9.2.2 clockevents_chain이 생성되는 원리 ... 139
        9.2.3 clockevents_chain에 tick_notifier를 등록하는 방법 ... 140
        9.2.4 clockevents_lock에 대한 스핀 락을 해제하는 원리 ... 142
   Chapter 10 CPU 비트맵에 수행 중인 CPU 등록과 HIGHMEM 관리를 위한 초기화 ... 144
      10.1. 핫플러그 정보를 담고 있는 비트맵에 init_task를 수행하는 CPU 추가하기 - boot_cpu_init() ... 144
      10.2. 하이 메모리 관리하기 - page_address_init() ... 146
   Chapter 11 전체 조망하기 - setup_arch() ... 149
   Chapter 12 unwind_init()∼early_trap_init() ... 152
      12.1. 스택 역추적하기 - unwind_init() ... 152
      12.2. 머신 정보를 담고 있는 machine_desc 구조체 구하기 - setup_machine() ... 153
      12.3. ATAG 정보 처리하기 - setup_arch() ... 154
      12.4. 부팅 파라미터 처리하기 - parse_cmdline() ... 156
      12.5. 리소스 트리 구성하기 - request_standard_resources() ... 158
      12.6. cpu possible 비트맵 초기화하기 - smp_init_cpus() ... 164
      12.7. ARM 예외 모드마다 스택 지정해주기 - cpu_init() ... 165
      12.8. 익셉션 핸들링을 위해 초기화하기 - early_trap_init() ... 167
      12.9. 인터럽트 핸들러 함수 살펴보기 ... 174
        12.9.1 IRQ 핸들러 호출하기 - asm_do_IRQ() ... 177
        12.9.2 인터럽트 이전으로 돌아가기 - ret_to_user 레이블 ... 179
   Chapter 13 프로세서 셋업하기 - setup_processor() ... 181
      13.1. setup_processor() 구조 알아보기 ... 181
      13.2. CPU ID 찾기 - read_cpuid_id() ... 183
      13.3. 프로세서 정보 찾기 - lookup_processor_type() ... 184
      13.4. 프로세서 아키텍처 정보 찾기 - cpu_architecture() ... 185
      13.5. 프로세서 캐시 타입 찾기 - cacheid_init() ... 189
      13.6. 프로세서 초기화 함수 호출하기 - cpu_proc_init() ... 193
   Chapter 14 메모리 페이징 준비하기 - paging_init() ... 196
      14.1. paging_init() 전체 구조 살펴보기 ... 196
      14.2. 메모리 타입 테이블 설정해주기 - build_mem_type_table() ... 198
      14.3. 메모리 정보 점검하기 - sanity_check_meminfo() ... 201
      14.4. 페이지 테이블 준비하기 - prepare_page_table() ... 203
        14.4.1 prepare_page_table() ... 203
        14.4.2 리눅스의 페이징 구조 ... 205
        14.4.3 페이지 디렉터리 엔트리 구하기 ... 206
        14.4.4 pmd_clear() ... 208
      14.5. 디바이스 영역 매핑 준비하기 - devicemaps_init() ... 210
      14.6. 하이 메모리 사용 준비하기 - kmap_init() ... 215
      14.7. 제로 페이지 초기화하기 ... 216
        14.7.1 메모리 할당하기 - __alloc_bootmem_nopanic() ... 217
        14.7.2 지정된 노드에서 fallback을 사용하여 메모리 할당받기 - alloc_bootmem_core() ... 218
        14.7.3 가상 주소를 page 구조체로 변환하기 - virt_to_page() ... 220
      14.8. D-Cache의 일관성 유지하기 - flush_dcache_page() ... 221
   Chapter 15 부트 타임 시 메모리 할당자 초기화하기 - bootmem_init() ... 223
      15.1. bootmem의 함수 흐름과 자료구조들 ... 224
      15.2. bootmem_init() 구조 알아보기 ... 229
      15.3. 램디스크 위치 찾기 - check_initrd() ... 230
      15.4. 노드의 뱅크 정보를 페이지 디렉터리에 반영하기 - bootmem_init_node() ... 231
        15.4.1 map_memory_bank() ... 233
        15.4.2 bootmem_bootmap_pages() ... 236
        15.4.3 find_bootmap_pfn() ... 238
        15.4.4 node_set_online() ... 239
        15.4.5 NODE_DATA() 매크로 ... 240
        15.4.6 init_bootmem_node() ... 242
        15.4.7 free_bootmem_node() ... 244
        15.4.8 reserve_bootmem_node() ... 245
      15.5. 0번 노드 제외시키기 - reserve_node_zero() ... 246
      15.6. 램디스크 노드 제외시키기 - bootmem_reserve_initrd() ... 248
      15.7 가용 페이지 없다고 설정하기 - bootmem_free_node() ... 248
      15.8 free_area 영역 초기화 ... 251
        15.8.1 free_area 구조체 ... 251
        15.8.2 free_area_init_node() ... 253
        15.8.3 free_area_init_core() ... 254
        15.8.4 init_currently_empty_zone() ... 256
        15.8.5 memmap_init() ... 257
   Chapter 16 mm_init_owner()∼preempt_disable() ... 264
      16.1. 메모리 소유자 설정하기 - mm_init_owner() ... 264
      16.2. 명령어 라인 저장해두기 - setup_command_line() ... 265
      16.3. per-cpu 데이터 초기화하기 - setup_per_cpu_areas() ... 266
      16.4. CPU 개수 구하기 - setup_nr_cpu_ids() ... 269
      16.5. SMP 상의 부팅 프로세스 등록하기 - smp_prepare_boot_cpu() ... 270
      16.6. 스케줄러를 사용하기 위해 자료구조 초기화하기 - sched_init() ... 272
        16.6.1 그룹 스케줄링 시 사용되는 task_group의 sched_entity 구조체와 runqueue 구조체를 위한 메모리 할당 ... 273
        16.6.2 root_domain, rt_bandwidth, task_group 관련 자료구조 초기화 ... 276
        16.6.3 시스템의 모든 possible cpu의 런큐 초기화 ... 278
        16.6.4 현재 태스크의 스케줄링 관련 값 초기화 및 로드밸런싱을 위한 인터럽트 핸들러 등록 ... 280
      16.7. 커널 선점 허용하기와 선점 막기 - preempt_enable() / preempt_disable() ... 281
   Chapter 17 빌려줄 후원자 구성하기 ... 283
      17.1. build_all_zonelists()에서 다루는 자료구조들 ... 283
      17.2. build_all_zonelists() 구조 알아보기 ... 285
      17.3. 존의 리스트 방식 결정하기 - set_zonelist_order() ... 287
      17.4. 폴백 리스트와 폴백 비트맵 구성하기 - __build_all_zonelists() ... 290
        17.4.1 build_zonelists() ... 291
        17.4.2 build_zonelists_in_node_order() ... 293
        17.4.3 build_zonelists_in_zone_order() ... 296
        17.4.4 build_thisnode_zonelists() ... 297
        17.4.5 build_zonelist_cache() ... 297
      17.5. 폴백 리스트 정보 출력하기 - mminit_verify_zonelist() ... 299
      17.6. 페이지 할당 요청을 처리할 노드 정하기 - cpuset_init_current_mems_allowed() ... 300
      17.7. 프리 페이지 개수 구하기 - nr_free_pagecache_pages() ... 300
      17.8. 페이지 모빌리티 ... 304
   Chapter 18 page_alloc_init()∼pidhash_init() ... 308
      18.1. 핫플러그 CPU를 위한 page 처리하기 - page_alloc_init() ... 309
      18.2. console 파라미터 처리하기 - parse_early_param() ... 311
      18.3. 특별한 파라미터 처리하기 - parse_args() ... 313
      18.4. 인터럽트 활성화 여부 확인하기 - irqs_disabled() ... 317
      18.5. 커널 예외 테이블 정의하기 - sort_main_extable() ... 318
      18.6. RCU 메커니즘 초기화하기 - rcu_init() ... 320
      18.7. IRQ를 사용하기 위한 준비하기 - early_irq_init() ... 323
      18.8. 인터럽트 초기화하기 - init_IRQ() ... 328
      18.9. 프로세스 정보를 빠르게 찾기 위한 구조 만들기 - pidhash_init() ... 331
   Chapter 19 init_timers()∼page_cgroup_init() ... 333
      19.1. 타이머 초기화하기 - init_timers() ... 334
        19.1.1 timer_cpu_notify() ... 335
        19.1.2 register_cpu_notifier() ... 336
        19.1.3 open_softirq() ... 337
      19.2. High Resolution 타이머 초기화하기 - hrtimers_init() ... 338
      19.3. softirq의 콜백 함수 등록하기 - softirq_init() ... 341
      19.4. xtime 설정하기 - timekeeping_init() ... 345
      19.5. 하드웨어 타이머 초기화하기 - time_init() ... 348
      19.6. clock 타임 초기화하기 - sched_clock_init() ... 350
      19.7. CPU의 인터럽트 활성화하기 - local_irq_enable() ... 352
      19.8. 루트 파일시스템으로 사용되는 init 램디스크 검사하기 ... 353
      19.9. 동적 메모리 할당을 위한 초기화 작업하기 - vmalloc_init() ... 353
      19.10. 덴트리와 아이노드 캐시에 대한 초기화 미리 수행하기 - vfs_caches_init_early() ... 355
      19.11. cpuset 서브시스템 초기화하기 - cpuset_init_early() ... 358
      19.12. memory 서브시스템 초기화하기 - page_cgroup_init() ... 360
   Chapter 20 bootmem 할당자를 종료하고 버디 시스템으로 교체 ... 363
      20.1. mem_init() 함수의 호출 관계와 자료구조의 상관 관계 ... 363
      20.2. mem_init() 구조 알아보기 ... 364
      20.3. 존재하지 않는 메모리 비트맵에 기록하기 - free_unused_memmap_node() ... 366
      20.4. 일반 프리 페이지 버디 시스템으로 이관하기 - free_all_bootmem_node() ... 368
        20.4.1 register_page_bootmem_info_node() ... 368
        20.4.2 free_all_bootmem_core() ... 370
        20.4.3 __free_pages_bootmem() ... 372
        20.4.4 __free_pages() ... 376
        20.4.5 free_hot_cold_page() ... 376
        20.4.6 __free_pages_ok() ... 378
      20.5. 하이 메모리 프리 페이지 버디시스템으로 이관하기 - free_area() ... 383
   Chapter 21 CPU 핫플러그 지원을 위한 초기화 ... 385
      21.1. cpu_hotplug 멤버 변수 초기화하기 - cpu_hotplug_init() ... 385
      21.2. CPU의 온라인→오프라인으로 변경 시 처리 ... 386
   Chapter 22 슬랩 메모리 할당자 활성화하기 - kmem_cache_init() ... 389
      22.1. 슬랩 할당자 개념과 구조체들 ... 389
      22.2. 슬랩 할당자의 중요 구조체 - kmem_cache와 kmem_list3 ... 391
      22.3. kmem_cache_init() 구조 알아보기 ... 394
      22.4. initkmem_list3[], cache_cache.nodelists[] 초기화 ... 399
      22.5. kmem_list3 배열에 연결하고 cache 축소시간 정하기 - set_up_list3s() ... 401
      22.6. cache의 확장 및 축소에서 사용될 페이지 오더 구하기 - cache_estimate() ... 402
      22.7. malloc_sizes와 cache_names ... 406
      22.8. cache 생성하기 - kmem_cache_create() ... 408
        22.8.1 kmem_cache_zalloc() ... 410
        22.8.2 calculate_slab_order() ... 411
        22.8.3 setup_cpu_cache() ... 412
        22.8.4 enable_cpucache() ... 414
      22.9. arraycache_init, kmem_list3 cache 생성 ... 414
      22.10. 정적으로 할당받은 메모리를 kmalloc()을 통해 할당받은 메모리로 대체하기 ... 417
   Chapter 23 kmem_trace_init()∼security_init() ... 420
      23.1. ID allocator 캐시 생성하기 - idr_init_cache() ... 421
      23.2. pageset 초기화하기 - setup_per_cpu_pageset() ... 421
      23.3. 인터리브 노드 지정하기 - numa_policy_init() ... 427
      23.4. 타이머 초기화 마무리하기 - late_time_init() ... 431
      23.5. BogoMIPS 측정하기 - calibrate_delay() ... 431
      23.6. 프로세스 식별자(ID) 할당을 위한 비트맵 만들기 - pidmap_init() ... 433
      23.7. 우선순위 트리의 자료구조 초기화하기 - prio_tree_init() ... 435
      23.8. anon_vma 슬랩 캐시 생성하기 - anon_vma_init() ... 435
      23.9. 객체에 사용자별로 자격 부여하기 - cred_init() ... 437
      23.10. fork()를 사용할 수 있게 자료구조 초기화하기 - fork_init() ... 438
      23.11. 프로세스 생성을 위한 캐시 초기화하기 - proc_caches_init() ... 439
      23.12. 버퍼 캐시 초기화하기 - buffer_init() 442
      23.13. 보안 키 준비하기 - key_init() ... 445
   Chapter 24 VFS에서 사용되는 다양한 캐시들 초기화하기 - vfs_caches_init() ... 449
   Chapter 25 radix_tree_init()∼ftrace_init() ... 468
      25.1. 래딕스 트리 관련된 자료구조 초기화하기 - radix_tree_init() ... 469
      25.2. 시그널을 사용할 준비하기 - signals_init() ... 470
      25.3. proc 파일시스템을 등록하고 마운트하기 - proc_root_init() ... 471
      25.4. 초기화하지 못한 서브시스템 등록하기 - cgroup_init() ... 472
      25.5. top_cpuset을 재설정하고 cpuset 파일시스템 등록하기 - cpuset_init() ... 474
      25.6. 태스크 통계 정보 인터페이스 초기화하기 - taskstats_init_early() ... 475
      25.7. 지연 정보 관리를 위한 준비 - delayacct_init() ... 477
        25.7.1 딜레이 어카운팅 ... 477
        25.7.2 dealyacct_init() ... 477
        25.7.3 task_delay_info 구조체와 delayacct_tsk_init() ... 478
      25.8. 쓰기 버퍼의 일관성 검사하기 - check_bugs() ... 481
   Chapter 26 메모리와 백킹 스토어 싱크하기 - 페이지 라이트백 ... 483
      26.1. 페이지 라이트백 메커니즘 ... 484
      26.2. 페이지 라이트백 활성화하기 - pdflush_init() ... 485
      26.3. pdflush 스레드 ... 487
      26.4. 페이지 라이트백 함수 지정하기 - pdflush_operation() ... 489
      26.5. 어떻게 주기적 페이지 라이트백, 강제적 페이지 라이트백 콜백 함수가 호출되나? ... 490
        26.5.1 주기적 페이지 라이트백 함수 - wb_kupdate() ... 490
        26.5.2 강제적 페이지 라이트백 함수 - background_writeout() ... 493
      26.6. 주기적 페이지 라이트백 초기화하기 - page_writeback_init() ... 494
   Chapter 27 커널 부팅의 마지막 함수 구조 알아보기 - rest_init() ... 496
   Chapter 28 함수를 실행할 커널 스레드 생성하기 - kernel_thread() ... 499
      28.1. kernel_thread() 구조 알아보기 ... 499
      28.2. 프로세서를 생성하는 게이트웨이 - do_fork() ... 500
      28.3. 부모 프로세스 복사하기 - copy_process() ... 504
   Chapter 29 새로 생성한 태스크 깨우기 ... 514
      29.1. wake_up_new_task() 구조 알아보기 ... 514
      29.2. 태스크의 런큐 가져오기 - task_rq_lock() ... 517
      29.3. 태스크의 우선순위 개선하기 - effective_prio() ... 518
   Chapter 30 커널 사용할 준비하기 - kernel_init() ... 522
      30.1. 현재 프로세스를 다른 CPU로 이주시키기 - sched_init_smp() ... 523
      30.2. 시스템 전반적으로 초기화 마무리하기 - do_basic_setup() ... 526
        30.2.1 rcu_sched_grace_period()를 실행할 스레드 생성하기 - rcu_init_sched() ... 527
        30.2.2 events 워크 큐 생성하기 - init_workqueues() ... 528
        30.2.3 cpuset 서브시스템의 top_cpuset 초기화하기 - cpuset_init_smp() ... 535
        30.2.4 khelper 워크 큐 생성하기 - usermodehelper_init() ... 536
        30.2.5 리눅스의 디바이스 모델 초기화하기 - driver_init() ... 538
        30.2.6 irq 정보를 proc 파일시스템에 등록하기 - init_irq_proc() ... 548
        30.2.7 커널이 모르는 서브시스템 호출하기 - do_initcalls() ... 549
      30.3. 초기화 다음을 준비하기 - init_post() ... 554
   Chapter 31 커널 스레드 데몬 ... 556
      31.1. 커널 스레드 데몬 - kthreadd() ... 556
      31.2. 시그널 무시하기 - ignore_signals() ... 559
      31.3. 나이스 값 설정하기 - set_user_nice() ... 562
      31.4. 태스크를 실행시킬 CPU 찾기 - set_cpus_allowed_ptr() ... 567
      31.5. 리스트를 포함하고 있는 실제 구조체 위치 찾기 - list_entry() ... 569
      31.6. 커널 스레드 생성하기 - create_kthread() ... 572
   Chapter 32 find_task_by_pid_ns()∼cpu_idle() ... 575
      32.1. PID로 태스크 찾기 - find_task_by_pid_ns() ... 576
      32.2. BKL 해제하기 - unlock_kernel() ... 579
      32.3. 스케줄링 클래스를 idle로 변경하기 - init_idle_bootup_task() ... 580
      32.4. RCU 메커니즘이 활성화되었음을 알리기 - rcu_scheduler_starting() ... 580
      32.5. 커널 선점 활성화하기 - preempt_enable_no_resched() ... 581
      32.6. 프로세스 스케줄링 수행하기 - schedule() ... 582
        32.6.1 schedule()의 진짜 알맹이 - __schedule() ... 582
      32.7. 리눅스 부팅 대장정의 끝 - cpu_idle() ... 584
APPENDIX
   Appendix A 어셈블러, gas 키워드 정리 ... 588
      A.1 ARM 명령어 기본 ... 588
        A.1.1 분기 명령어 ... 588
        A.1.2 산술 연산 명령어 ... 588
        A.1.3 논리 연산 명령어 ... 588
        A.1.4 비교 연산 명령어 ... 589
        A.1.5 데이터 전송 명령어 ... 589
        A.1.6 상?
닫기