[커널 19차] 1주차

2022.05.16 22:30

리턴 조회 수:456

스터디 일자 : 2022.05.14

도서 및 진행범위 : 리눅스 커널 내부구조 0p~ 53p

 

[다음주차 진행 준비내용]
- 리눅스 커널 컴파일 실습해보기

- git 사용법 공부해보기

- 다음 주차 진행 범위 : 리눅스 커널 내부구조 53p~93p

 

 


 

 

[스터디 진행 내용]

 

운영체제 = 자원 관리자

운영체제는 물리적 자원(RAM, CPU, DISK 등)을 추상화하여 (Task, Memory, File) 관리하는 자원 관리자라고 할 수 있다.
 

EyetpmWhR-rbIR_5pmqvB2gAsqrZeo7ZfCYtaCLw

 

 

커널 내부에는 자원 별로 이를 관리하는 관리자가 있다.

스케줄러는 태스크 (프로세스)의 생성과 실행, 상태 전이 (실행중->대기->등등), 스케줄링, 시그널 등을 관리하고, 메모리 관리자는 태스크에 할당되는 메모리를 관리하며 파일시스템은 디스크 블록을 추상화하여 파일을 읽고 쓸 수 있게 해준다.

네트워크 관리자도 비슷하게 소켓으로 다른 태스크와 데이터를 주고 받을 수 있도록 한다.

디바이스 드라이버는 디바이스 (네트워크 카드, 디스크)와 일정한 규약에 따라 통신한다. (PCI, USB, NVMe, ATA등등)

 

 

운영체제는 태스크를 위해 이러한 자원을 관리하며, 태스크는 시스템 호출 인터페이스를 통해서 운영체제가 제공하는 일종의 서비스(파일 읽기 등)를 이용할 수 있다.

 


리눅스 소스 구조
https://makelinux.github.io/kernel/map/
리눅스 소스는 github.com/torvalds/linux나 kernel.org에서 받을 수 있다.
Linux kernel map ← 사이트에서 원하는 부분의 그림을 확대하면 더 자세한 구조를 볼 수 있습니다.

 

 

vNTzTrkfaIG4ywdEWV7EYoTMDkhZmof2kbLCrNB8

 

 

현재 기준 (5.18-rc5) 디렉토리 구조

9KAyD2X4ursBxYQqkte058ZuPuhDR8YpQ9eo7ykK

  • Documentation - 커널의 각종 문서 자료들
  • arch - arm, x86, mips, powerpc, … 등 아키텍처에 의존하는 코드들 (header, misc, bsetup 포함)
  • init - 초기화 코드
  • mm - 메모리 관리자 (Memory Management)
  • kernel - 커널의 코어한 부분들 (스케줄러, 락 등등)
  • fs - 파일시스템
  • drivers - 디바이스 드라이버들
  • tools - 커널 개발에 도움이 되는 도구들 (왜 스크립트랑 따로 있을까요? ← script는 kernel build에 도움이 되는 부분이고 tools는 빌드된 kernel이 동작하는 타겟 환경에서 사용할 수 있는 utility들의 집합이 아닐까요? 라고 생각했는데 tools/build 같은 것이 있어서 좀 혼동되네요)
  • scripts - 커널 개발에 도움이 되는 스크립트들 (checkpatch, get_maintainers, faddr2line, decode_stacktrace 등등)
     

 

커널 빌드 및 설치 (실습)

# wget https://git.kernel.org/torvalds/t/linux-5.18-rc6.tar.gz
# gzip -d linux-5.18-rc6.tar.gz
# tar -xvf linux-5.18.rc6.tar
# cd linux-5.18.rc6.tar
# cp /boot/config-$(uname -r) .config
# make olddefconfig
# make menuconfig
# make -j$(nproc)
# sudo make headers_install modules_install install # install headers, modules, and the kernel

 

 

 

“make menuconfig”로 kernel compile option들을 하나씩 지정하여 최종 .config 옵션 설정 파일을 만든 후에 빌드 할 수 있지만 각 ARCH (아키텍쳐) 별로 defconfig를 지정해 두고 이를 기준으로 .config 파일을 만들 수 있습니다.

예를 들어 aarch64 (또는 arm64)의 defconfig에 해당하는 https://github.com/torvalds/linux/blob/master/arch/arm64/configs/defconfig를 보면 기존에 정해둔 kernel compile option들이 있는데 이 정보들에 각 subsystem들의 Kconfig와 조합하여 최종 .config를 만들어 낼 수도 있습니다.

이때는 “make ARCH=arm64 defconfig” 와 같이 수행 합니다. 이때 defconfig는 각 모델이나 보드별로 rpi4_defconfig, odroid_defconfig와 같이 여러 종류의 defconfig로 관리 될 수 있습니다. 보통 보드 제조사에서 제공 합니다.

make로 빌드하면 vmlinux와 ${ARCH}/boot/Image가 생성됩니다.

vmlinux는 virtual memory linux의 약자로 ELF 형식이며 UNIX 계열에서 Executable and Linkable Format을 의미 합니다.

vmlinux 파일의 시작부분에는 ELF header 형식의 정보가 있으며 이 정보를 바탕으로 RAM에 각 section들을 적재하면 Image와 같이 실제 RAM에서 실행되는 형식의 데이터를 가지게 됩니다.

실제 Image를 생성할 때도 vmlinux의 ELF header 형식을 objdump가 해석하여 Image라는 파일로 만들어 내는 것 입니다.

그런데 실제로 RAM에서 실행되는 형태의 바이너리는 00으로 채워진 부분과 같이 저장소에 저장하는 형태로는 비효율적이기 때문에 압축하여 저장하기 위해서 make zImage 또는 make bzImage로 압축하여 실행 바이너리를 생성하여 저장하고 실제로 동작할 때는 boot-loader가 이를 RAM으로 압축을 풀어서 적재를 한 후에 실행하게 됩니다.

실제로 Image, zImage, bzImage는 Linux kernel을 실행 하는데 사용하며 debug 정보를 포함하는 vmlinux는 검토용으로 사용합니다.

zImage 와 bzImage의 챠이가 궁금해져 찾아 봤는데

https://wiki.kldp.org/KoreanDoc/html/EmbeddedKernel-KLDP/kernel-image-file-structure.html

에 설명이 있었습니다. x86 제약 때문에 생겨난 차이점이었네요.

 

✨yocto로 kernel과 rootfs를 소스 코드로 부터 빌드하여 qemu로 실행하는 방법을 linux kernel build on yocto 에 필요한 명령어들로 간단히 정리하였습니다.

linux kernel build on WSL and QEMU 는 좀 더 간단히 kernel만 빌드하여 qemu로 동작하는 방법을 정리하였습니다.

 

커널 이미지

QVbCMdY0nDDR8M5rrfSRAEi0yhSu0o_5LddwZZ_c

https://mintnlatte.tistory.com/164
커널 이미지는 piggy, head, misc, bsetup, bbootsect로 이루어져 있다.

bbootsect는 예전에 커널 자체에 부트로더가 포함되던 시절에 사용하던 것으로 현대의 부트 프로토콜에선 사용하지 않는다.

최근의 부트로더(그럽,릴로 등)는 이러한 내용을 숙지하고 bsetup부터 실행한다.

bsetup에는 스택 및 힙 초기화 등등의 초기화 코드가 포함되어있고, head와 misc는 압축된 커널인 piggy.gz의 압축을 푼 후 메모리에 로드한다.

(위 내용은 ARCH 마다 달라지므로 현재는 자세히 이해하려 하지 말고 다음 ARCH 공부 할 때 고민하셔도 될 것 같습니다.)
 

 

커널 내에 생성되는 각 파일들의 관계

b21bkms2F-RKYgm6zG8JABzOHF5CbMdCpBCSfYLd

 

 

 

(4) objcopy(making raw binary image) example code

(4) objcopy(making raw binary image) example code
gcc -c test.c // test.o made
objcopy -O binary -j .text loop.o binfile // make binary file bin file
hexdump -C binfile // see raw binary image

vmlinux = virtual memory linux
bvmlinux = big vmlinux x86 640KiB 이내로 적재가 되지 않은 kernel 이미지
 

p.44

0WXafC6hLyHxbfay9lzFR0O5XKEJN01NaEHXFDK0

 

HXkhpRaNhTCZSoUTneqDLvh4j-axjBI9Sbj7_G81

 

 

 

[진행 내용 및 질의 응답 내용]

 

1. 용어 태스크와 프로세스 차이점이 있는지?

    a. 동일한 용어로 봐도 무방함

        i. 단, 태스크는 프로세스다라고 보기는 또 힘든것이, 프로세스는 스레드 개념을 포함하고 있음. 
            - 스레드 마다 스택을 포함, 스레드는 프로세스에 포함 관계임.
            - 프로세스가 실행되면 메인 스레드가 생성되는데, 메인스레드가 죽으면 프로세스도 종료된다.

              (프로세스의 다른 스레드가 실행 중이라면 강제로 종료하거나, 종료를 기다리게 됨)
        ii. 책에서는 “프로세스 = 실행중인 프로그램, 스레드 = 수행의 단위” 라고 한다.
        iii. 리눅스에서는 프로세스와 스레드의 구분이 크게 없다.

            자원을 얼마나 공유하냐에 따라 스레드라고도 하고, 프로세스라고도 한다 (?)

            => (음.. 그렇다기보단 리눅스에서 코드상에서 크게 구분하지 않는 걸로 알고 있어요.

                 대신 하나의 프로세스 내의 스레드들이 공유하는 자원이 서로 다른 프로세스 사이에 비해서 많은 정도의 차이가 있죠. ‘프로세스 = 스레드’는 아니죠.)
    b. What is difference between task/thread/process?


2. Inode 의 데이터 정보도 동일하게 디스크 블록에 할당되어 저장되는지?
    a. No (디스크의 메타 영역에 별도 저장)
        i. inode는 메타 영역에 저장되어있으며, 커널 부팅 후 메모리에 load 됨
        ii. 유저가 파일을 찾을 경우, 과정은 아래와 같음
           파일 찾는 명령어 입력 -> 쉘 (명령어 해석기) -> system all -> 커널 동작(vfs)

           -> inode 확인(lookup) -> file system (ext4, ntfs 등) -> Block layer subsystem

           -> storage device driver -> storage device

               R1dSUJwVx-YNtvPR5Mqomai5SPoIe_gMhHhz7vrx

    b. 아이노드는 파일시스템이 무엇이냐에 관계없이 추상화된 자료구조이기 때문에, 아이노드가 직접 디스크에 저장된다기보단 파일시스템별로 아이노드에 들어가는 데이터를 저장하는 방식이 다른 것으로 알고 있습니다. 그리고 디스크에서 매번 파일의 메타데이터를 읽어오는 건 너무 느리니까 슬랩 할당자를 사용해서 아이노드 캐시를 만들어서 빠르게 접근할 수 있도록 합니다. 이와 비슷하게 덴트리 캐시도 파일의 경로(디렉토리의 트리 구조)를 빠르게 탐색하기 위해서 존재합니다.
    c. 아이노드: 유닉스 계열 파일시스템에서, 파일시스템 객체(파일/디렉토리 등)를 표현하는 자료 구조 (operating system's in-memory representation of filesystem metadata)

 

3. 메타 공간은 해당 메타의 주소값으로 접근하나요? (메타공간: 파일시스템 부가정보)

    a. yes 
    b. vfs(virtual file system) 에서 먼저 메모리를 접근 


4. 파일시스템의 sync 라는 용어는 flush 와 같은가요? 
    a. yes
    b. 메모리에서 쓰인 파일 내용을 실제 “물리디스크” 에 기록시키는 용어를 일컫음

 

 

sY6IzsE2aoyEy-8avnP15RknxyWOWu8m-DwR18Rl

 

5. 리눅스 커널 소스 디렉토리 경로 중, script 와 tools 차이점은?
    a. 상단 디렉토리 구조 항목 참조


6. 모듈이란?
    a. 커널 이미지에는 포함되지 않지만 동적으로 불러올 수 있는 커널 코드 (?)
        i. 동적으로 load,unload 가 가능한 실행파일 (?)
             1. 조립식 개념으로 생각하면 편할듯


7. interrupt service routine 란?
    - https://namu.wiki/w/%EC%9D%B8%ED%84%B0%EB%9F%BD%ED%8A%B8
    - Exception vector는 하드웨어적으로 정해져 있음.
      예) ARM Exception vector

          XHvKrRqhKoSm7MPImMQg44DWb3p9nk9ck2ly81GL

          여기서 irq가 인터럽트에 해당하는 부분. (irq == Interrupt ReQuest)

 

8. 32bit 프로세서에서는 일반적으로 램을 4기가 까지만 접근할 수 있으나, 인텔 프로세서에서의 PAE(physical address extension) 같은 경우에는 32비트 프로세서에서도 2^36 = 64기가 까지 접근할 수 있도록 한다. 64비트 프로세서에서는 4단계/5단계 페이징 중 무엇을 사용하느냐에 따라서 2^48또는 2^57만큼의 가상주소를 사용할 수 있다. (인텔 기준)
    - 주소에서 사용되지 않는 남은 부분은 개발자가 꼼수로 데이터를 저장하는데 사용되기도 함. (커널에서 hardware tag-based KASAN 같은 경우는 실제로 포인터의 상위 비트 일부를 사용해서 새너타이저를 구현함)


9. bss(block starting symbol)란? 
    a. 초기화가 되지 않은 데이터를 저장하는 공간 (0으로 초기화 됨)

    lwGztf-tMttc26KPFAxV-NOOHTMNvTNd0AVWdq6y

 

10. bootstrap: 스스로 부팅하는 과정.

 

 

11. virtual memory: Disk에 넣으면 physical memory (?). demand paging. 
    - 작은 메모리를 크게 쓸 수 있게하는 기법 -> 이라기 보단 실제의 물리 주소 공간이 아니라 커다란 가상의 주소 공간을 사용하도록 하는 기법
        - 가상의 주소 공간을 만들어서 프로세스 안에서 주소 공간을 일정한 규칙으로 사용하고, 주소 공간을 최대 공간을 사용하면서 동시에 물리메모리(RAM)의 공간을 절약하여 사용하는 기법
    - 요구 페이징은 실제로 사용하는 시점에 페이지를 물리 메모리에서 할당하는 기법
    - 가상 메모리는 프로세스가 독립된 (물리 주소를 쓰지 않고) 가상 주소 공간을 얻는다는게 매우 큰 이점
    - 가상 메모리가 없어도 컨텍스트 스위칭이 가능하다 (컨텍스트 스위칭 할 때 address space 정보는 해당 프로세스로 교체 필요) -> 다시말해 컨텍스트 스위칭과 가상 메모리가 별개의 기술.
    - 관련 정보 링크


12. context switching - 프로세스 간 스케줄링을 위하여 현재 CPU가 동작하는 프로세스의 정보를 교체하여 동작시킬 프로세스의 정보로 교환. 
    - tcb(thread context block)에 스레드 정보를 저장 후 스케줄링 우선순위에 따라 다음 스레드의 tcb 를 세팅 후 진행한다. 


13. MMU(memory management unit): page table: CPU에 포함된 하드웨어로, 가상 주소와 페이지 테이블을 통해 MMU가 물리 주소를 알아낼 수 있음


14. 도커에서 centOS로 /usr/src/kernels/에 접근했는데 책 처럼 파일이 없습니다. 왜 인가요?
    a. 도커에 대해 찾아봤을 때, 커널은 원래 시스템에 연결해서 사용한다고 합니다.


15. make 과정에서 사용 가능한 옵션들
    a. INSTALL_MOD_STRIP=1 
        i. make 모듈할 때, 모듈이 생각보다 커서 필요 없는 부분 제외하고 make할 때
    b. -j24 ( -j`nproc` 로도 가능, nproc는 유저가 사용할 수 있는 최대 프로세스 수를 출력합니다.)
        i. 가능하면 멀티로 24개 분할해서 빠르게라는 뜻
        ii. 동시에 실행할 작업 수를 지정하는 옵션
    c. ARCH=architecture, CROSS_COMPILE=compiler toolchain
        i.컴퓨터가 x86_64여도 arm64용으로 크로스빌드할 수도 있음

 

커널 개발 주기

하나의 개발 주기는 8~9주 정도 소요, 처음 1~2주는 머지 윈도우로 새로운 기능을 추가하고, 그 이후 -rc1, -rc2 등등 릴리즈 후보 버전이 나오다가 토발즈가 버전을 확정하면 릴리즈 버전이 나온다.

리눅스의 자세한 개발 프로세스는 커널 소스의 Documentation/process에 정리가 잘 되어있다.
    - rc(release candidate)
 

 

토발즈의 독재 시스템(?)

hImtTdV7qjUBpmPsEuajPclpdGXsp85EZmMdZZdI

 

 

 

 

 

 

 

 

번호 제목 글쓴이 날짜 조회 수
공지 [공지] 스터디 정리 노트 공간입니다. woos 2016.05.14 626
127 [커널 18차] 56주차 kkr 2022.06.18 71
126 [커널 17차] 92~93주차 ㅇㅇㅇ 2022.06.11 93
125 [커널 18차] 54주차 kkr 2022.06.04 82
124 [커널 19차] 3주차 리턴 2022.06.04 217
123 [커널 18차] 53주차 kkr 2022.05.29 93
122 [커널 17차] 91주차 ㅇㅇㅇ 2022.05.28 64
121 [커널 19차] 2주차 리턴 2022.05.28 169
120 [커널 17차] 90주차 ㅇㅇㅇ 2022.05.22 149
119 [커널 18차] 52주차 kkr 2022.05.21 124
» [커널 19차] 1주차 리턴 2022.05.16 456
117 [커널 17차] 89주차 ㅇㅇㅇ 2022.05.15 65
116 [커널 18차] 51주차 kkr 2022.05.14 159
115 [커널 18차] 50주차 kkr 2022.05.10 207
114 [커널 17차] 88주차 ㅇㅇㅇ 2022.05.08 101
113 [커널 19차] 0주차 - 오리엔테이션 리턴 2022.05.07 600
112 [커널 17차] 86~87주차 ㅇㅇㅇ 2022.04.30 101
111 [커널 17차] 84~85주차 JSYoo5B 2022.04.16 86
110 [커널 17차] 83주차 ㅇㅇㅇ 2022.04.03 92
109 [커널 17차] 82주차 ㅇㅇㅇ 2022.03.27 65
108 [커널 17차] 81주차 ㅇㅇㅇ 2022.03.19 132
XE Login