디버깅을 통해 배우는 리눅스 커널의 구조와 원리 -1-

라즈베리 파이로 따라하면서 누구나 쉽게 이해할 수 있는 리눅스 커널

신입 리눅스 시스템 개발자부터 5년차 개발자가 실무를 하기 위해 알아야 할 리눅스 커널의 주요 서브시스템을 다룹니다!

실전 개발에서 신입 사원 옆에 친절한 선배 개발자가 앉아서 리눅스 커널에 대해 꼼꼼하게 알려주듯, 리눅스 커널을 쉽고 친절하게 설명하는 책입니다. 이 책은 최신 버전(LTS: 4.19)의 리눅스 커널 소스를 함수 흐름을 따라가며 자세히 분석하고 ftrace와 TRACE32 같은 디버깅 툴을 활용해 커널의 동작 원리를 설명합니다. 또한 라즈베리 파이에서 리눅스 커널의 소스코드를 직접 수정해 설치한 다음 커널을 디버깅하는 방법을 다룹니다. 각 장에서 소개하는 커널 디버깅 방법은 실무 개발에 그대로 적용할 수 있습니다.

 

▣ [1부] 커널 디버깅(ftrace), 프로세스, 인터럽트, 인터럽트 후반부, 워크큐 편 먼저 커널을 디버깅하는 방법과 함께 ftrace 사용법을 소개합니다. 커널을 실행하는 주인공인 프로세스와 인터럽트를 커널이 처리하는 세부 동작 원리를 다룹니다. 인터럽트 후반부를 처리하는 IRQ 스레드(threaded IRQ)와 Soft IRQ 기법과 커널에서 후반부를 처리하는 워크큐에 대해 설명합니다.

 

▣ [2부] 타이머, 동기화, 스케줄링, 시스템 콜, 시그널, 가상 파일 시스템, 메모리 관리 편 커널이 시간의 흐름을 관리하는 동작 원리와 동기화 기법(스핀락, 뮤텍스)을 다룹니다. 여러 프로세스의 실행 흐름을 관리하는 스케줄링의 세부 구현 방식과 시스템 콜과 시그널을 커널에서 어떤 방식으로 처리하는지 설명합니다. 다양한 파일 시스템을 공존해 실행시킬 수 있는 가상 파일 시스템과 커널의 메모리를 관리하는 방식에 대해 다룹니다.

부록으로 리눅스 커널의 메일링 리스트를 활용하는 방법과 리눅스 커널에 기여하는 방법을 자세히 소개합니다.

 

도서 상세 이미지

김동현

LG전자에서 11년째 임베디드 리눅스 BSP 엔지니어로 일하고 있다. 주로 리눅스 커널 드라이버를 안정화(Kernel Stability Troubleshooting)하거나 보드를 브링업하는 과제에 참여했다. 로우 레이어 소프트웨어(부트로더, 리눅스 커널 드라이버)의 다양한 문제를 해결할 수 있는 디버깅 방법에 관심이 많으며 실무 지식을 블로그를 통해 다른 개발자와 공유하는 것을 즐긴다.

  • ▣ 01장: 리눅스 소개와 전망
    • 1.1 리눅스와 리눅스 커널은 왜 배워야 할까?
      • 1.1.1 리눅스는 왜 배워야 할까?
      • 1.1.2 리눅스 커널은 왜 배워야 할까?
    • 1.2 리눅스의 전망
      • 1.2.1 운영체제란 무엇인가?
      • 1.2.2 우리는 어떤 운영체제를 쓰고 있나?
    • 1.3 리눅스의 역사
      • 1.3.1 유닉스의 탄생
      • 1.3.2 1991년: 리누스 토발즈의 등장
      • 1.3.3 리눅스가 인기 있는 이유는 무엇일까?
    • 1.4 리눅스는 어디에 쓰일까?
      • 1.4.1 안드로이드
      • 1.4.2 자동차(AutoMotive)
      • 1.4.3 사물인터넷(IoT: Internet of Things) 디바이스
    • 1.5 임베디드 리눅스 개발 단체
      • 1.5.1 리눅스 커널 커뮤니티
      • 1.5.2 CPU 벤더
      • 1.5.3 SoC 벤더
      • 1.5.4 보드 벤더 및 OEM
    • 1.6 임베디드 리눅스 개발을 잘 하려면 무엇을 알아야 할까?
      • 1.6.1 디바이스 드라이버
      • 1.6.2 리눅스 커널
      • 1.6.3 CPU 아키텍처
      • 1.6.4 빌드 스크립트와 Git
    • 1.7 라즈베리 파이와 리눅스 커널
      • 1.7.1 라즈베리 파이 실습 보드
      • 1.7.2 리눅스 커널 버전
      • 1.7.3 라즈비안 버전
      • 1.7.4 ARM 아키텍처
    • 1.8 정리
    •  
  • ▣ 02장: 라즈베리 파이 설정
    • 2.1 라즈베리 파이란?
    • 2.2 라즈베리 파이 설정
      • 2.2.1 라즈베리 파이 실습을 위한 준비물
      • 2.2.2 라즈베리 파이 설치
      • 2.2.3 라즈베리 파이 기본 설정
    • 2.3 라즈베리 파이 커널 빌드
      • 2.3.1 라즈비안 버전과 커널 소스 버전
      • 2.3.2 라즈비안 커널 소스코드 내려받기
      • 2.3.3 라즈비안 리눅스 커널 빌드
      • 2.3.4 라즈비안 리눅스 커널 설치
      • 2.3.5 전처리 코드 생성
      • 2.3.6 리눅스 커널 소스의 구조
    • 2.4 objdump 바이너리 유틸리티
    • 2.5 라즈베리 파이 사용 시 주의사항
    • 2.6 정리
    •  
  • ▣ 03장: 커널 디버깅과 코드 학습
    • 3.1 디버깅이란?
      • 3.1.1 디버깅은 문제 해결 능력의 지름길
      • 3.1.2 디버깅과 코드 학습 능력
    • 3.2 printk
    • 3.3 dump_stack() 함수
    • 3.4 ftrace
      • 3.4.1 ftrace란?
      • 3.4.2 ftrace는 어떻게 설정할까?
      • 3.4.3 ftrace 메시지는 어떻게 분석할까?
      • 3.4.4 ftrace 로그는 어떻게 추출할까?
      • 3.4.5 ftrace는 커널 코드 분석의 안내자
    • 3.5 임베디드 디버거의 전설 TRACE32
    • 3.6 커널 디버깅용 Debugfs 드라이버 코드
    • 3.7 정리
    •  
  • ▣ 04장: 프로세스
    • 4.1 프로세스 소개
      • 4.1.1 프로세스란?
      • 4.1.2 태스크란?
      • 4.1.3 스레드란?
    • 4.2 프로세스 확인하기
      • 4.2.1 ps 명령어로 프로세스 목록 확인
      • 4.2.2 ftrace에서 프로세스 확인하기
    • 4.3 프로세스는 어떻게 생성할까?
      • 4.3.1 _do_fork() 함수 소개
      • 4.3.2 유저 레벨 프로세스를 생성할 때 _do_fork() 함수의 처리 흐름
      • 4.3.3 커널 프로세스 생성 시 _do_fork() 함수의 흐름
    • 4.4 유저 레벨 프로세스 실행 실습
      • 4.4.1 기본 유저 레벨 프로세스 실행 실습 및 ftrace 로그 분석
      • 4.4.2 exit() 함수로 프로세스가 종료되는 과정 및 ftrace 로그 분석
    • 4.5 커널 스레드
      • 4.5.1 커널 스레드란?
      • 4.5.2 커널 스레드의 종류
      • 4.5.3 커널 스레드는 어떻게 생성할까?
    • 4.6 커널 내부 프로세스의 생성 과정
      • 4.6.1 _do_fork() 함수
      • 4.6.2 copy_process() 함수 분석
      • 4.6.3 wake_up_new_task() 함수 분석
    • 4.7 프로세스의 종료 과정 분석
      • 4.7.1 프로세스 종료 흐름 파악
      • 4.7.2 do_exit() 함수 분석
      • 4.7.3 do_task_dead() 함수 분석
      • 4.7.4 do_task_dead() 함수를 호출하고 난 후의 동작
    • 4.8 태스크 디스크립터(task_struct 구조체)
      • 4.8.1 프로세스를 식별하는 필드
      • 4.8.2 프로세스 상태 저장
      • 4.8.3 프로세스 간의 관계
      • 4.8.4 프로세스 연결 리스트
      • 4.8.5 프로세스 실행 시각 정보
    • 4.9 스레드 정보: thread_info 구조체
      • 4.9.1 thread_info 구조체란?
      • 4.9.2 thread_info 구조체 분석
      • 4.9.3 thread_info 구조체의 주소 위치는 어디일까?
      • 4.9.4 컨텍스트 정보 상세 분석
      • 4.9.5 cpu 필드에 대한 상세 분석
      • 4.9.6 thread_info 구조체 초기화 코드 분석
    • 4.10 프로세스의 태스크 디스크립터에 접근하는 매크로 함수
      • 4.10.1 current 매크로란?
      • 4.10.2 current_thread_info() 매크로 함수 분석
    • 4.11 프로세스 디버깅
      • 4.11.1 glibc의 fork() 함수를 gdb로 디버깅하기
      • 4.11.2 리눅스 유틸리티 프로그램을 이용한 실행 추적
    • 4.12 정리
    •  
  • ▣ 05장: 인터럽트
    • 5.1 인터럽트 소개
      • 5.1.1 인터럽트란?
      • 5.1.2 리눅스 커널 인터럽트의 주요 개념
      • 5.1.3 인터럽트를 잘 알아야 하는 이유
      • 5.1.4 리눅스 커널에서의 인터럽트 처리 흐름
    • 5.2 인터럽트 컨텍스트
      • 5.2.1 인터럽트 컨텍스트란?
      • 5.2.2 ftrace와 커널 로그로 인터럽트 컨텍스트 확인해보기
      • 5.2.3 in_interrupt() 함수란?
      • 5.2.4 인터럽트 컨텍스트에서 스케줄링을 하면 어떻게 될까?
    • 5.3 인터럽트 핸들러는 언제 호출될까?
      • 5.3.1 인터럽트 벡터 분석
      • 5.3.2. 인터럽트 벡터에서 스택 푸시 확인
      • 5.3.3. 인터럽트 핸들러의 호출 흐름 분석
    • 5.4 인터럽트 핸들러는 어떻게 등록할까?
      • 5.4.1 인터럽트 핸들러의 등록 과정 분석
      • 5.4.2 인터럽트 핸들러의 초기화 과정 디버깅
      • 5.4.3 인터럽트 핸들러 등록 시 플래그 설정
    • 5.5 인터럽트 디스크립터
      • 5.5.1 인터럽트 디스크립터란?
      • 5.5.2 인터럽트 발생 횟수는 어떻게 저장할까?
    • 5.6 인터럽트는 언제 비활성화해야 할까?
    • 5.7 인터럽트 디버깅
      • 5.7.1 /proc/interrupts
      • 5.7.2 ftrace 인터럽트 이벤트
      • 5.7.3 ftrace로 인터럽트 핸들러 함수 파악하기
    • 5.8 정리
    •  
  • ▣ 06장: 인터럽트 후반부 처리
    • 6.1 인터럽트 후반부 기법이란?
      • 6.1.1 인터럽트 후반부 기법을 적용하는 이유
      • 6.1.2 인터럽트 컨텍스트에서 많은 일을 하면 어떻게 될까?
      • 6.1.3 Top Half/Bottom Half란?
      • 6.1.4 인터럽트 후반부 처리 기법의 종류
      • 6.1.5 어떤 인터럽트 후반부 처리 기법을 적용해야 할까?
    • 6.2 IRQ 스레드(threaded IRQ)
      • 6.2.1 IRQ란?
      • 6.2.2 IRQ 스레드 확인
    • 6.3 IRQ 스레드는 어떻게 생성할까?
      • 6.3.1 IRQ 스레드는 언제 생성할까?
      • 6.3.2 라즈베리 파이에서 IRQ 스레드 생성 과정 디버깅
    • 6.4 IRQ 스레드는 누가 언제 실행할까?
      • 6.4.1 IRQ 스레드를 깨우는 코드 분석
      • 6.4.2 IRQ 스레드 핸들러인 irq_thread() 함수 분석
      • 6.4.3 IRQ 스레드의 전체 실행 흐름 정리
    • 6.5 IRQ 스레드 디버깅 실습
      • 6.5.1 ftrace를 이용한 IRQ 스레드 동작 확인
      • 6.5.2 IRQ 스레드 생성 실습
      • 6.5.3 IRQ 스레드 처리 함수 실행 시각 측정
    • 6.6 Soft IRQ 소개
      • 6.6.1 Soft IRQ 서비스란?
      • 6.6.2 Soft IRQ의 전체 흐름
      • 6.6.3 후반부 기법으로 Soft IRQ를 언제 쓸까?
      • 6.6.4 Soft IRQ는 왜 알아야 할까?
    • 6.7 Soft IRQ 서비스
      • 6.7.1 Soft IRQ 서비스
      • 6.7.2 Soft IRQ 서비스 핸들러는 언제 등록할까?
      • 6.7.3 Soft IRQ 서비스 핸들러의 등록 과정 실습
    • 6.8 Soft IRQ 서비스는 언제 요청할까?
      • 6.8.1 Soft IRQ 서비스 요청의 전체 흐름
      • 6.8.2 raise_softirq() 함수 분석
      • 6.8.3 irq_stat 전역변수 분석
      • 6.8.4 Soft IRQ 서비스를 요청했는지는 누가 어떻게 점검할까?
    • 6.9 Soft IRQ 서비스는 누가 언제 처리할까?
      • 6.9.1 Soft IRQ 서비스 실행 진입점은 어디일까?
      • 6.9.2 Soft IRQ 서비스 요청 점검
      • 6.9.3 Soft IRQ 서비스 실행
      • 6.9.4 ksoftirqd 스레드 깨우기
    • 6.10 ksoftirqd 스레드
      • 6.10.1 ksoftirqd 스레드란?
      • 6.10.2 ksoftirqd 스레드는 언제 깨울까?
      • 6.10.3 ksoftirqd 핸들러 run_ksoftirqd() 함수 분석
    • 6.11 Soft IRQ 컨텍스트에 대해
      • 6.11.1 Soft IRQ 컨텍스트 시작점은 어디일까?
      • 6.11.2 Soft IRQ 컨텍스트는 언제 시작할까?
      • 6.11.3 Soft IRQ 컨텍스트 확인
    • 6.12 태스크릿
      • 6.12.1 태스크릿이란?
      • 6.12.2 태스크릿 자료구조
      • 6.12.3 태스크릿은 어떻게 등록할까?
      • 6.12.4 태스크릿의 전체 실행 흐름 파악
      • 6.12.5 태스크릿 실행 요청은 어떻게 할까?
      • 6.12.6 태스크릿은 언제 실행할까?
    • 6.13 Soft IRQ 디버깅
      • 6.13.1 ftrace의 Soft IRQ 이벤트 소개
      • 6.13.2 /proc/softirqs를 이용한 Soft IRQ 서비스 실행 횟수 확인
    • 6.14 정리
    •  
  • ▣ 07장: 워크큐
    • 7.1 워크큐 소개
      • 7.1.1 워크큐의 주요 개념
      • 7.1.2 워크큐의 특징
      • 7.1.3 워크큐와 다른 인터럽트 후반부 기법과의 비교
      • 7.1.4 워크큐로 인터럽트 후반부 코드를 설계하는 과정
      • 7.1.5 워크큐를 잘 알아야 하는 이유
    • 7.2 워크큐의 종류
      • 7.2.1 alloc_workqueue() 함수 분석
      • 7.2.2 7가지 워크큐
    • 7.3 워크란?
      • 7.3.1 work_struct 구조체
      • 7.3.2 워크는 어떻게 초기화할까?
    • 7.4 워크를 워크큐에 어떻게 큐잉할까?
      • 7.4.1 워크를 워크큐에 큐잉하는 예제 코드 살펴보기
      • 7.4.2 워크큐 전체 흐름도에서 워크를 워크큐에 큐잉하는 과정
      • 7.4.3 워크를 워크큐에 큐잉하는 인터페이스 함수 분석
      • 7.4.4 __queue_work() 함수 분석
      • 7.4.5 __queue_work() 함수에서 호출하는 워크큐 내부 함수 분석
    • 7.5 워크는 누가 언제 실행하나?
      • 7.5.1 워크 실행의 출발점인 worker_thread() 함수 분석
      • 7.5.2 process_one_work() 함수 분석
    • 7.6 워커 스레드란?
      • 7.6.1 워커와 워커 스레드
      • 7.6.2 worker 구조체
      • 7.6.3 워커 스레드는 누가 언제 만들까?
      • 7.6.4 워커 스레드를 생성하는 create_worker() 함수 분석
      • 7.6.5 create_worker() 함수에서 호출한 워크큐 커널 함수 분석
      • 7.6.6 worker_thread() 함수 분석
    • 7.7 워크큐 실습 및 디버깅
      • 7.7.1 ftrace 워크큐 이벤트
      • 7.7.2 라즈베리 파이에서 ftrace를 이용한 워크큐 동작 확인
      • 7.7.3 인터럽트 후반부 처리 실습과 로그 분석
    • 7.8 딜레이 워크
      • 7.8.1 딜레이 워크란?
      • 7.8.2 딜레이 워크의 전체 흐름
      • 7.8.3 딜레이 워크는 어떻게 초기화할까?
      • 7.8.4 딜레이 워크 실행의 시작점은 어디일까?
      • 7.8.5 딜레이 워크는 누가 언제 큐잉할까?
    • 7.9 라즈베리 파이에서의 딜레이 워크 생성 실습
      • 7.9.1 패치 코드의 내용과 작성 방법
      • 7.9.2 ftrace 로그 설정
      • 7.9.3 ftrace 로그 분석
    • 7.10 정리
  • 48쪽, 페이지 상단 명령어의 3번째 줄

    # fonts-unfonts-core
    

    ==>

    # apt-get install fonts-unfonts-core
    
  • 84쪽, 본문 3번째 줄

    인터럽트의 속성 정보는 위 05번째 줄과 같이

    ==>

    인터럽트의 속성 정보는 위 06번째 줄과 같이