최근 수정 시각 : 2024-12-15 20:06:46

Linux/커널

파일:상위 문서 아이콘.svg   상위 문서: Linux
<colbgcolor=#ffdf33><colcolor=#000> Linux Kernel
리눅스 커널

파일:Linux 로고(글자 포함).svg

개발 리누스 토르발스
플랫폼 AMD64, IA-32, ARM, MIPS, PowerPC, SPARC(64bit), RISC-V
개발 언어 C언어[1], 어셈블리어, Rust[2]
소스 공개 여부 GPLv2[3] 하에 오픈 소스
최신 단기 지원 버전 6.11(.x) (stable)
최신 장기 지원 버전 6.12(.x) (longterm)
최신 개발 버전 (RC) 6.13-rc(x) (mainline)
홈페이지 파일:Linux 로고(글자 포함).svg 파일:Linux 로고 화이트(글자 포함).svg
소스 코드 파일:Linux 로고.svg 파일:Linux 로고 화이트.svg 파일:GitHub 아이콘.svg 파일:GitHub 아이콘 화이트.svg

1. 개요2. 기술적 설명
2.1. 부트로더2.2. 부팅 과정
2.2.1. 커널 초기화2.2.2. initramfs 이미지 로드2.2.3. init 프로세스
2.3. 가상 파일 시스템
3. 컴파일 방법
3.1. 준비3.2. 설정3.3. 빌드3.4. 설치3.5. 기타, 여담
4. 커널 개발5. 역사

[clearfix]

1. 개요

파일:external/www.makelinux.net/Linux_kernel_diagram.png
Linux 커널 구조도

Linux 커널.

Linux 커널은 단일형 커널 구조를 가지며, 모듈화되어 있어, 컴파일 후에 모듈을 로드시킬 수 있다. 디바이스 드라이버가 이런 형태로 사용된다. 리눅스 커널 모듈은 .ko[4]의 확장자를 가지고 있다.

Linux는 커널에 대한 개별적인 설계를 통해 커널에 포함해야 할 기능을 최소화할 수 있다. 예를 들면 장치에 포함되지 않은 디바이스 드라이버는 포함하지 않을 수 있다. 그래서 똥컴이나 임베디드 시스템 등 성능이 낮거나 낡은 하드웨어라도 Linux를 사용할 수 있다.

대부분 Linux의 커널 이미지는 /boot/vmlinuz-(커널 버전)-(기타 내용)[5]에 있다. [6] 이 vmlinuz라는 이름은 vm: 가상 메모리 지원, linu: Linux, z: 압축된 이미지, 즉 압축된 가상 메모리 지원 Linux라는 뜻이다.

2. 기술적 설명

2.1. 부트로더

과거의 Linux 커널과 배포판에서는 LILO(LInux LOader)를 사용했지만, 2000년대 이후의 Linux 배포판들은 GRUB을 사용한다.[7]

LILO는 하드디스크 상의 물리적인 위치를 기점으로 부팅을 하지만 GRUB는 파일명과 커널이 위치하고 있는 파티션을 기점으로 부팅하므로 커널을 업데이트하더라도 파일명만 바뀌지 않으면 그대로 부팅이 가능하다.

2.2. 부팅 과정

2.2.1. 커널 초기화

부트로더가 Linux 커널 이미지를 부트로더에서 설정된 파라미터와 로드하면, 부트로더가 압축 루틴으로 점프하여 커널을 압축해제하고, start_kernel() 함수를 실행시킨다. 이 함수는 스택 BSS를 초기화하고, 나머지 부팅을 위한 하드웨어의 초기화 작업을 시행하고, 나머지 하드웨어[8]를 초기화시킨다.

2.2.2. initramfs 이미지 로드

커널 초기화가 끝나면, initramfs를 임시로 / 디렉토리에 적재한다. 이 이미지는 최종적인 루트 파일시스템을 적재하기 위해 사용하는데 필요한 기본적인 유틸리티가 포함되어있다.
다음으로 initramfs 이미지 파일에서 /init 스크립트를 찾아 실행시킴으로써 루트 파일시스템을 적재시킨다. 이 스크립트는 다음과 같은 과정을 주로 거친다.
  • /proc[9], /dev[10], /sys[11]를 마운트한다.
  • 커널에서 사용할 커널 모듈[12]을 로드한다.
  • 실제 루트 파일시스템[13]을 /에 적재시키고, init 프로세스를 생성하고 실행한다.

과거에는 initrd라는 압축된 파일시스템 이미지를 사용하였는데, 이는 실제 파일시스템을 압축시킨 것이어서, 실행하려면 램디스크를 로드하고 적재해야했다. 이 과정이 리소스를 많이 사용하여, 리눅스 커널 2.6.13부터 cpio 아카이브 형식을 사용해 메모리에 바로 적재될 수 있는 initramfs를 사용하기 시작했다.

2.2.3. init 프로세스

이후 사용자 영역에 데몬 프로세스로 init를 생성하는데, 이 프로세스는 시스템 서비스를 실행하고 네트워크, 파일 시스템 등을 초기화한다. 이후 Linux 시스템의 전체적인 관리를 하는데 다음과 같은 역할을 한다.
  • 프로세스들을 관리하며, 부모 프로세스가 먼저 종료되어 끊겨진 자녀 프로세스(일명 고아 프로세스)를 자기 자녀로 설정한다.
  • 저널링, 알람, 사용자 권한을 관리한다.

init를 대체하기 위해서 등장한 것이 systemd인데, 데몬을 병렬로 실행하고 작은 데몬들은 단일 프로세스 내에 합쳐서 기능 추가와 부팅 속도 개선을 이뤘다. 그러나 기존의 init와는 설계 철학이 완전히 달랐기 때문에 등장 당시부터 큰 논란거리가 되었고, 대형 Linux 배포판은 2010년대 초반부터 중반 사이에 init에서 전환했으나 반감을 가진 Devuan 같은 일부 배포판은 systemd를 사용하지 않고 OpenRC같은 init을 사용하기도 한다. 특히 Gentoo Linux는 OpenRC를 사용할지 systemd를 사용할지 선택할 수 있다.

2.3. 가상 파일 시스템

Linux에서는 모든 파일 시스템[14] Microsoft Windows에서처럼 C 드라이브, D 드라이브 등으로 나누지 않고, 하나의 계층 구조 아래에[15] 탑재하는데, 이를 가능하게 하는 것이 가상 파일 시스템이다.

모든 파일 시스템은 슈퍼블록이라는 구조체를 가지는데, 이 구조체는 파일 시스템에 관한 정보[16]를 저장한다. 가상 파일 시스템 레이어가 저장장치를 시스템에 탑재시킬 때, 이 구조체를 읽어들이고, 마운트 테이블에 이 구조체를 저장한다. 그리고 나서 파일 시스템의 정보를 저장할 공간을 메모리에 마련한 후, 해당 드라이브를 가상 파일 시스템에 통합시킨다.

3. 컴파일 방법

3.1. 준비

  • 필요한 의존성 패키지를 설치한다. make, ncurses, gcc, g++, binutils가 최소 요건이며, 이외에도 비필수 의존성이 많이 있다. 아치 Linux 기준 xmlto, kmod, inetutils, bc, libelf, git, cpio, perl, tar, xz 패키지가 더 필요하다.
  • 커널 작업을 할 작업용 디렉터리를 만든다.
  • 해당 작업용 디렉터리에 들어가 Linux 커널 사이트에서 원하는 버전의 커널 tar.xz 파일을 받는다.
  • 디지털 서명과 파일의 체크섬을 검사한다. 서버의 파일이 조작되어 멀웨어가 포함되었을수도 있기 때문이다.
  • 압축을 푼다. ( tar -xvf linux-(버전).tar.xz로 충분하다.)
  • make mrproper로 소스 트리를 청소한다.

3.2. 설정

커널 설정을 생성한다. 크게 두 가지의 방법이 있다.
  1. 이미 Linux를 실행하고 있다면, 현재의 커널 설정을 베이스로 할 수 있다. zcat /proc/config.gz > .config 명령어로 현재 커널 설정을 덤프하는 방법이 있고, make localmodconfig로 현재의 커널 모듈을 베이스로 한 최소식을 설정하는 방법이 있다.
  2. 직접 설정한다. 설정을 위한 인터페이스에는 여러 가지가 있는데, 이 중 하나를 실행하면 된다.
    • make menuconfig, make nconfig: 콘솔창 메뉴 기반 세팅. 각각 ncurses5, 혹은 ncurses 필요.
    • make xconfig: KDE 기반 그래픽 환경 세팅. packagekit-qt5 필요.
    • make gconfig: Gtk 기반 그래픽 환경 세팅.

3.3. 빌드

이제 설정한 커널을 빌드할 시간이다. make 명령으로 커널을, make modules 명령으로 커널 모듈을 빌드한다. 시간을 빨리 돌리고 싶다면 -j n 옵션으로 멀티태스킹을 활성화시킨다. n의 추천은 CPU의 가용 스레드 수 = 소켓 × 코어 × 논리적 스레드; 이다. 만약 SMT를 지원하는 6코어 CPU를 사용 중이라면 12개의 스레드를 동원할 수 있고 -j 12 옵션을 사용할 수 있다. 기본 옵션은 단일 스레드 동작이기 때문에 매우 느리다.

3.4. 설치

여기서부터 모든 명령어는 root로 실행하거나 sudo를 붙여서 실행해야 한다. 시스템을 변경하는 것이기 때문이다.
  • make modules_install 명령으로 커널 모듈을 현재 파일시스템에 복사한다.
  • x86, x86_64 기준으로 arch/x86/boot/bzImage가 커널이다. 이 파일을 vmlinuz-(커널 버전)-(접미어)[17] 형태의 이름으로 /boot에 복사한다. 만약 /boot가 별도의 파티션일 경우 먼저 마운트해야 한다.
  • 자기 배포판에 맞는 방식으로 initrd (일부 배포판에서는 initramfs)를 만들어서 /boot에 복사한다.
  • System.map을 /boot/System.map-(커널 버전) 형태로 복사하고, /boot/System.map에 다시 그 파일의 링크를 건다.
  • (선택) 커널 설정할 때 쓴 .config 파일을 /boot/config-(커널 버전) 형태로 붙여넣는다. 문제 해결 때 커널 설정을 보기 위함이다.
  • 새로운 커널로 부팅하도록 부트로더 설정을 바꾼다.
  • 새 커널로 재부팅한다.

3.5. 기타, 여담

윈도우의 WSL 내 Linux 환경 자체는 대소문자를 구별하도록 되어 있지만 호스트 운영체제는 그렇지 않다. 따라서 WSL 내에 호스트 운영체제의 파티션을 마운트한 경로에서 작업을 하는 경우, 파일명이 충돌하는 문제가 발생할 수 있어 커널 컴파일 또한 정상적으로 진행되지 않을 수 있다.

컴파일 시간의 경우 선택한 옵션, 컴퓨터 성능, 병렬 작업 여부 등 수많은 변수가 있지만 [18] 평균적으로 고성능 컴퓨터에서는 30분에서 1시간 사이의 시간이 필요하다며 사양이 낮아질수록 시간은 더 오래 걸린다. 극단적으로 최적화를 하거나, 커널 커스터마이징이 필요하거나, Gentoo Linux, Linux From Scratch 등의 모든 것을 컴파일하는 배포판을 사용하지 않는 이상은 우분투 등의 바이너리 인스톨을 이용하는 배포판을 사용하는 것이 좋다. 2000년대의 Linux 관련 서적에서는 커널 컴파일이 후반부의 한 장 정도로 포함되어 있었으나, 이제는 Linux 커널 자체도 규모가 커졌고 커널 개발을 하지 않는다면 단순 사용을 위해서 커널을 직접 컴파일할 필요도 없어졌다.

Linux 커널의 가장 많은 부분을 차지하고 있는 부분은 드라이버 부분이 가장 많은 부분(1200만 줄)을 차지하고 있고 커널 자체의 코드 (12 만줄)크기는 상대적으로 작다. 그렇다 보니 임베디드 환경같이 커널 크기를 줄여야 하고 고정된 하드웨어에서만 작동해도 되는 환경에서는 드라이버를 쓸 부분만 남기고 전부 날려버려도 된다. 이 경우 컴파일 시간과 커널 이미지도 극적으로 줄어든다.

4. 커널 개발

언어는 C언어를 중심으로 어셈블리어를 일부 사용하고 있다. C++의 사용은 리누스 토르발스가 의도적으로 막고 있다. 버전 6.1부터 러스트도 개발에 사용되지만 드라이버 개발부분에서 일부만 사용되고 핵심코어 부분은 여전히 C언어로만 개발된다. #

현대에 와서는 코드의 양이 너무 많아져서, 한 사람이 Linux 커널에 대해 완전히 아는 건 불가능한 수준이 되었다. 2018년 기준 Linux 커뮤니티에 많이 기여하는 미국 대기업 기준으로 한 회사의 Linux 커널 개발자가 250~300여명 수준이다. 이런 수준의 개발자가 되기 위해서는 Linux 커널에 대한 책만 70여권 이상 읽어야 한다는 사람도 있다. 삼성전자 개발자들이 국내에서 가장 많이 기여하고 있는데 전체 연간 기여의 3%에 불과하다. 이런 회사 출신 개발자는 Linux 커널에 기여하는 게 곧 본인들 업무다. 2017년까지 약 1400여개의 회사에서 Linux 커널 개발에 참여했다. 연간 기여량의 약 40%를 20여개 대기업 [19]에서 담당하고 있다. 돈을 받지 않고 개인적으로 기여하는 사람의 비중은 약 10% 정도인데 이들은 점점 줄어들고 있다. 왜냐하면 너무나도 방대한 커널 코드에 지쳐 그만두거나, 기업에서 이들을 채용해 가기 때문이다.

Linux 커널의 개발은 크게 메인테이너(Maintainer)와 기여자(Contributor)로 나뉜다. 기여자가 패치를 보내면 메인테이너는 그 패치의 리뷰를 하고 서브시스템을 관리하는 등 중심적인 역할을 맡는다. 국내 Linux 커널 메인테이너는 2015년 기준 약 30여명으로 알려져 있다.

2022년 리누스 토발즈는 Linux 커널 개발자들이 고등학생처럼 벼락치기로 일정을 간신히 맞추거나 이마저도 지키지 못해 코드 제출이 늦는다고 깠다. #

5. 역사

1991년 4월 리누스 토르발스 80386 보호모드에서 돌아가는 첫 Linux 커널의 개발을 시작했다. 8월 말 완료된 0.01 버전의 코드 라인은 10,239줄이었다. 2015년 6월 공개된 버전 4.1은 약 1950만줄 이상이고 14,000여명의 프로그래머가 기여했다. [20]

1996년 버전 2.0이 나온 이후에는 약 2년마다 마이너 버전(0.x)이 올라가고[21], 약 2개월마다 패치 버전(0.0.x)이 오르는 식이었으나, 2.6 버전은 이례적으로 7년 넘게 유지되었다. 결국 2011년 7월 리누스 토르발스가 버전 명명 규칙을 바꾸면서 버전이 3.0으로 올라갔고, 마이너 버전이 19~20 정도 나온 후에는 메이저 버전이 올라가게 되었다. 즉 버전 3.0부터는 메이저 버전이 바뀌었다 해서 꼭 내용물이 크게 바뀌었다는 것을 의미하지는 않는다.

2012년 12월경 버전 3.8부터는 처음 지원했던 80386 지원을 중단했다.

2018년 버전 4.17부터는 Blackfin, CRIS, FRV, M32R, Metag, MN10300, Score, Tile 등 관리가 되지 않았던 CPU 명령어 집합 지원을 중단하고 관련 드라이버 50만줄을 소스코드에서 삭제했다.

2021년 리누스 토르발스 아이테니엄 시리즈가 2021년 2월 단종되자 바로 아이테니엄 시리즈 지원중단을 선언했다. 12월에는 3DNow! 처럼 인텔에 밀려 잘 사용되지 않는 AMD 자체 명령어 셋 지원도 중단했다. #

2022년 버전 6.1부터 HEDT CPU 지원 강화 및 손상된 코어 감지가 지원된다 또한 장치 드라이버 개발부분에서 Rust가 도입된다. 그리고 빅리틀 프로세서를 위한 새로운 프로세스 스케줄링 Nest가 도입된다. 또한 인텔 80486, 펜티엄 지원도 중단했다. 실제로 6.1.2커널을 적용한 Tinycore Linux 14.0 버전은 펜티엄 MMX급 이상에서만 동작한다고 한다.


[1] 버전 5.18부터 C11 사용 [2] 버전 6.1부터 일부 디바이스 드라이버에 한정해서 사용 [3] GPL-2.0-only with Linux-syscall-note # [4] Kernel Object(커널 객체) [5] 보통 generic이라고 한다. [6] /boot이 별도의 파티션일 경우 그 파티션의 루트 디렉토리에 있다. [7] 흔히 가정용 PC로 사용되는 인텔 CPU의 x86_64 아키텍쳐의 리눅스 한정이다. ARM이나, RISC-V 같은 경우, u-boot나, UEFI를 이용한 부트로더를 직접 구성하는 경우도 많다. UEFI와 대응하여, 별도의 부트로더를 거쳐서 부팅되는 것이 아닌, Linux Kernel Image 자체를 efi 바이너리로 내보내어, UEFI 동작 과정에서 바로 Kernel Boot를 해주는 EFI Stub Boot와 같은 기능도 있다. [8] CPU, RAM, 파일시스템 [9] 프로세스 관련 정보를 담고 있다. [10] 디바이스 파일을 담고 있다. [11] 커널 관련 정보를 담고 있다. [12] 주로 하드웨어 드라이버 코드를 포함하고 있다. [13] C드라이브라고 생각하면 된다. [14] ext4, NTFS, FAT [15] / 디렉토리 아래에 모든 파일 시스템을 탑재한다. [16] 파일 시스템 전체의 크기, 최대 파일 사이즈, 블록의 크기 등 [17] generic, lts 등 [18] 후술할 Linux From Scratch에서 하라는대로만 하면 4코어에 램 4기가여도 10분정도밖에 안걸린다. 하지만 모든 옵션을 선택할(!!!) 경우 아무리 좋은 컴도 몇시간씩 걸릴 수 있다. [19] 인텔, 오라클, AMD, ARM, NVIDIA, 삼성전자, 화웨이 등 [20] 참고로 1976년 Bell 연구소에서 나온 6번째 유닉스 개정판은 약 9000줄이었다. [21] 이 때는 마이너 버전이 홀수이면 개발 버전, 짝수이면 안정 버전이었기 때문에 마이너 버전업마다 버전이 0.2씩 올라갔다.

파일:CC-white.svg 이 문서의 내용 중 전체 또는 일부는 문서의 r2130에서 가져왔습니다. 이전 역사 보러 가기
파일:CC-white.svg 이 문서의 내용 중 전체 또는 일부는 다른 문서에서 가져왔습니다.
[ 펼치기 · 접기 ]
문서의 r2130 ( 이전 역사)
문서의 r79 ( 이전 역사)

분류