맨위로가기

Vmlinux

"오늘의AI위키"는 AI 기술로 일관성 있고 체계적인 최신 지식을 제공하는 혁신 플랫폼입니다.
"오늘의AI위키"의 AI를 통해 더욱 풍부하고 폭넓은 지식 경험을 누리세요.

1. 개요

Vmlinux는 유닉스 계열 운영체제 커널 이미지 파일의 한 종류로, 특히 가상 메모리를 지원하는 커널을 의미한다. 이 이름은 vmunix의 변형으로, 압축되지 않은 리눅스 커널 이미지를 나타낸다. bzImage는 vmlinux의 압축된 형태이며, 부트로더를 통해 시스템 메모리에 로드되어 운영체제 부팅 과정에 사용된다.

더 읽어볼만한 페이지

  • 리눅스 커널 - 적재 가능 커널 모듈
    적재 가능 커널 모듈은 운영 체제 커널의 기능을 확장하거나 수정하기 위해 사용되며, 메모리 효율성, 시스템 유지보수, 개발 편의성을 제공하지만, 성능 저하, 보안 취약성, 호환성 문제 등의 단점도 존재한다.
  • 리눅스 커널 - 리눅스 리브레
    리눅스 리브레는 자유 소프트웨어 철학에 따라 리눅스 커널에서 독점 바이너리 블롭을 제거한 커널로, 보안과 안정성 향상을 가져오지만 일부 하드웨어 기능 제한을 초래할 수 있으며, 여러 리눅스 배포판에서 사용된다.
Vmlinux
기본 정보
파일 이름vmlinux
설명실행 파일, 리눅스 커널 포함

2. 용어

전통적으로 유닉스 플랫폼은 커널 이미지를 '/unix' 또는 'unix'라는 이름으로 불렀다. BSD 등에서 가상 메모리 기능이 개발되면서, 이 기능을 지원하는 커널임을 구별하기 위해 'vm-'이라는 접두사를 붙여 'vmunix'라는 이름이 사용되었다.[24] 'vmlinux'라는 이름은 이러한 'vmunix'의 명명법을 따른 것이다. 리눅스에서는 커널 이미지를 압축하는 기능이 추가되었는데, 압축된 커널 이미지에는 '압축됨(zipped)'을 의미하는 문자 'z'를 이름 끝에 덧붙여 'vmlinuz'라고 부른다. 이는 주로 gzip과 같은 방식으로 압축된다.[24][1]

3. 위치

전통적으로 리눅스 커널 이미지는 파일 시스템 계층의 루트 디렉터리 (`/`)에 위치했다. 그러나 부트로더가 하드 디스크에 접근하기 위해 바이오스 드라이버를 사용해야 했는데, 일부 i386 시스템에서는 바이오스의 INT 13H 인터럽트 제한으로 인해 하드 디스크의 처음 1024개 실린더까지만 접근할 수 있는 문제가 있었다.

이러한 제한을 극복하기 위해, 리눅스 배포판들은 사용자가 하드 디스크 시작 부분에 별도의 파티션을 생성하여 부트로더와 커널 관련 파일을 저장하도록 권장했다. GRUB, LILO, SYSLINUX 등이 대표적인 부트로더다. 이 파티션에는 부팅에 필요한 파일 외에도 볼륨 부트 레코드가 올바르게 설정되어야 하는데, 예를 들어 XFS 파일 시스템은 해당 공간 확보 문제로 부트 파티션으로 사용하기 어려울 수 있다.[10]

관례적으로 이 부팅 전용 파티션은 시스템 부팅 후 /boot 디렉터리에 마운트되었다. 이러한 방식은 나중에 파일시스템 계층구조 표준(FHS)에 의해 표준화되었으며, FHS는 리눅스 커널 이미지가 / 또는 /boot에 위치할 것을 권장한다 (FHS 버전 2.3의 섹션 3.5.2 참조). 하지만 실제로 이를 강제하는 기술적인 제한은 존재하지 않는다.[25][2] 안전을 위해 커널 업데이트 시에만 /boot 파티션을 마운트하는 경우도 있다.

4. 압축

vmlinux라는 이름에서 파생된 `vmlinuz` 파일명의 마지막 문자 `z`는 커널 이미지가 압축되었음을 나타낸다(예: gzip 압축).[1]

전통적으로 부팅 가능한 커널 이미지를 생성할 때, 커널은 gzip을 사용하여 압축되었다. 리눅스 커널 버전 2.6.30부터는[3][11] 압축률이 더 높은 LZMA 또는 bzip2 알고리즘을 사용한 압축도 지원하기 시작했다. 이후 LZO,[4] xz,[5] LZ4[6] 및 zstd[7] 압축 방식에 대한 지원도 추가되었다.

압축된 커널 이미지는 부팅 과정 초기에 압축을 해제하는 작은 코드를 포함한다. 부트 로더가 압축된 커널 이미지를 메모리에 로드하면, 이 코드가 커널 코드를 압축 해제하여 실행 준비를 한다. 일부 시스템에서는 압축 해제 과정 동안 콘솔에 점(.)을 표시하여 진행 상황을 나타내기도 한다.

압축 해제 과정 자체는 부팅 시간에 큰 영향을 주지 않는다. 그러나 과거 i386과 같은 일부 아키텍처에서는 부팅 시 읽어들일 수 있는 데이터 크기에 매우 엄격한 제한이 있었기 때문에 커널 이미지 압축이 필수적이었다. ''bzImage'' 형식이 개발되면서 이러한 제약은 상당 부분 완화되었다.

SPARC 아키텍처의 경우, 리눅스 커널 이미지는 일반적으로 vmlinux 파일을 단순히 gzip으로 압축한 형태이다.[12] 이는 SPARC 시스템에서 자주 사용되는 SILO 부트 로더가 gzip으로 압축된 이미지를 직접 읽어 압축을 해제할 수 있기 때문이다.

현대의 부트 로더는 대부분 설정 파일이나 부팅 시 명령을 통해 커널 이미지 파일을 지정할 수 있으므로, 실제 파일 이름이 중요하지는 않다. 하지만 관습적으로 압축된 커널 이미지 파일은 `vmlinuz` 또는 `zImage`라는 이름을 사용하는 경우가 많다.

5. bzImage

리눅스 커널 크기가 증가함에 따라 일부 아키텍처에서 커널 이미지를 저장할 공간이 부족해지는 문제가 발생했다. 이를 해결하기 위해 개발된 형식이 bzImage(''big zImage'')이다.[11] bzImage는 커널 코드를 연속되지 않은 메모리 영역에 나누어 저장함으로써 기존의 크기 제한을 극복한다.

bzImage는 gzip 등의 알고리즘을 사용하여 압축된다.[3][11] 이름의 'bz' 접두사 때문에 bzip2 압축을 사용하는 것으로 오해하기 쉽지만, 실제로는 관련이 없다.[1]

bzImage 파일은 특정 구조를 가지며, 압축된 vmlinux 파일을 포함하는 형태로 구성된다.[8] 커널 소스에 포함된 `extract-vmlinux` 스크립트를 이용하면 이 압축된 커널 이미지를 추출할 수 있다. bzImage 파일의 상세한 구조와 생성 과정, 그리고 부팅 시 동작 방식은 하위 문단에서 자세히 설명한다.

5. 1. bzImage 구조

bzImage의 구조


리눅스 커널이 발전하면서 커널의 크기가 커지자, 일부 아키텍처에서는 압축된 커널 코드를 저장할 공간 부족 문제가 발생했다. 이를 해결하기 위해 커널을 연속되지 않은 메모리 영역에 나누어 저장할 수 있는 bzImage(''big zImage'') 형식이 개발되었다.

bzImage는 리눅스 2.6.30 버전까지 gzip을 사용하여 압축되었으며,[3] 이후 버전에서는 다양한 압축 알고리즘이 추가되었다. 이름의 'bz' 접두사가 bzip2 압축을 의미하는 것처럼 보일 수 있지만, 실제로는 그렇지 않다.[1] (bzip2 패키지는 종종 'bzless', 'bzcat' 등 'bz'로 시작하는 도구 이름을 사용한다.)

bzImage 파일은 특정 형식을 가지며, 초기에는 `bootsect.o` + `setup.o` + `misc.o` + `piggy.o` 파일을 연결하여 만들어졌다.[8] 이 중 `piggy.o` 파일의 데이터 섹션에는 gzip 등으로 압축된 vmlinux 파일이 포함되어 있다. 커널 소스 내 `scripts/extract-vmlinux` 스크립트를 사용하면 이 압축된 커널 이미지를 풀 수 있다. 일부 배포판(레드햇 등)에서는 커널 디버깅 정보가 포함된 `kernel-debuginfo` RPM 패키지를 제공하며, 여기에 원본 `vmlinux` 파일이 들어있기도 하다. 이 파일은 보통 `/usr/lib/debug/lib/modules/커널_버전/vmlinux` 경로에 설치된다.

리눅스 커널 이미지는 일반적으로 커널 소스 디렉토리에서 다음 명령으로 빌드할 수 있다.



make



커널 버전 2.6 이후, x86 (i386 및 x86-64) 아키텍처에서는 위 명령이 내부적으로 아래 명령과 동일하게 처리되어 bzImage를 생성한다.



make bzImage



bzImage 생성 과정은 여러 단계를 거친다. 먼저 커널에 정적으로 링크될 모든 오브젝트 코드(*.o, *.a)가 `vmlinux.o`로 링크된다. 동시에 모든 오브젝트 파일에서 심볼 정보를 추출하여 `.tmp_kallsyms2.o` (숫자는 설정에 따라 다름) 파일이 만들어진다. 이 두 파일을 링크하여 최종적으로 커널 실행 파일인 `vmlinux`가 생성된다. 이후 `vmlinux` 파일로부터 System.map 파일(커널 심볼 테이블)이 만들어진다.

다음으로 커널 부팅 및 압축 해제 관련 루틴 빌드가 시작된다.

  • 압축 커널 생성: `vmlinux` 파일은 GNU Binutils의 objcopy[16] 명령을 통해 불필요한 ELF 섹션 헤더와 심볼 정보가 제거된 `arch/x86/boot/compressed/vmlinux.bin` 파일로 변환된다. 이 바이너리 파일은 gzip 등의 알고리즘으로 압축되어(`vmlinux.bin.gz` 등) 특수한 ELF 오브젝트 파일인 `piggy.o` 내부에 데이터로 포함된다.[17] `piggy.o`는 압축된 커널 본체를 담고 있는 핵심 요소이다.
  • 압축 해제 및 저수준 코드 생성: 커널 이미지 앞부분에 위치할 `head_32.o` 또는 `head_64.o` (아키텍처 비트에 따라 다름)는 BIOS로부터 얻은 하드웨어 정보를 처리한다.[13] `misc.o`는 `piggy.o`에 포함된 압축된 커널 본체를 메모리에서 해제하는 코드를 담고 있다. 이 과정에서 "Uncompressing Linux..."[14] 메시지가 콘솔에 출력된다.[15] 이들(`head_$(BITS).o`, `misc.o` 등)과 `piggy.o`를 링크하여 `arch/x86/boot/compressed/vmlinux`라는 중간 단계의 실행 파일이 생성된다(이것은 최종 `vmlinux` 파일과 다르다).
  • 부트 로더 코드 생성: 커널 이미지의 가장 앞부분(엔트리 포인트 `_start`)에 위치할 부트 코드는 `arch/x86/boot/header.o`[18]에 포함되어 있으며, 나중에 커널 압축 해제 루틴을 호출한다. 이 코드와 비디오 BIOS 처리 등 다른 저수준 코드들이 링크되어 `arch/x86/boot/setup.elf` 실행 파일이 만들어진다.


최종적으로 bzImage는 다음과 같이 생성된다.

1. `arch/x86/boot/setup.elf` 파일은 `objcopy` 명령을 통해 raw 바이너리 형식의 `arch/x86/boot/setup.bin`으로 변환된다. 이 파일은 커널 부팅 초기에 실행되는 코드를 담는다.

2. `arch/x86/boot/compressed/vmlinux` 파일 역시 `objcopy` 명령을 통해 raw 바이너리 형식의 `arch/x86/boot/vmlinux.bin`으로 변환된다. 이 파일은 압축 해제 코드와 압축된 커널 본체(`piggy.o` 내용 포함)를 담는다.

3. 이 두 개의 raw 바이너리 파일(`setup.bin`과 `vmlinux.bin`)이 순서대로 결합되어 최종적으로 `arch/x86/boot/bzImage` 파일이 완성된다.

따라서 bzImage 파일의 구조는 본질적으로 다음과 같이 요약할 수 있다.



bzImage = setup.bin + vmlinux.bin

setup.bin <---(raw binary)--- setup.elf <--- header.o + main.o + more...

vmlinux.bin <---(raw binary)--- head_(BITS).o + misc.o + more... + piggy.o

piggy.o <---(compressed + embedded)--- vmlinux <--- vmlinux.o + .tmp_kallsyms2.o <--- *.o *.a

`|

System.map



여기서 각 `.bin` 파일은 해당 `.elf` 파일에서 심볼 및 재배치 정보를 제거하고 메모리에 직접 로드하여 실행할 수 있도록 변환된 raw 바이너리 형태이다.[16][19] 빌드 완료 시 출력되는 메시지 중 "Setup is X bytes"는 `setup.bin`의 파일 크기를, "System is Y kB"는 `vmlinux.bin` 내부의 압축 해제된 커널 본체의 크기를 나타낸다.

5. 2. 부팅 과정

bzImage는 개발 과정에서 초기 부팅 시 메모리 제약을 극복하기 위해 점프 명령어 등을 활용하여 복잡하게 구성된다.[20] x86 시스템 부팅 과정은 다음과 같다.

1. 커널 이미지 로드: BIOS에서 시작된 부트로더는 커널 이미지와 initrd를 메모리에 로드한다. 커널 이미지는 'Setup'과 'System' 두 부분으로 나뉘어 로드된다.

  • 'Setup': 부트로더 바로 뒤 메모리 주소에 로드되며, BIOS 등의 예약 영역을 덮어쓰지 않도록 주의한다.
  • 'System': 메모리 주소 0x100000 (1MB) 이후 영역에 로드된다. 이 영역은 리얼 모드에서는 접근할 수 없으므로 덮어쓰기 문제가 없다.
  • initrd: 'System'보다 뒷부분 메모리 주소에 로드된다.

2. Setup 실행: 'Setup' 부분은 BIOS 인터럽트 루틴을 사용하여 `header.o` 등의 처리를 거쳐 `head_$(BITS).o` 코드를 실행한다. 이 과정에서 CPU를 프로텍티드 모드로 전환한다.

3. 커널 압축 해제: `head_$(BITS).o`에서 `misc.o`가 호출되어 'System' 부분에 있는 압축된 커널 본체를 메모리에 압축 해제한다.

4. 커널 초기화 (어셈블리 코드 위주): 압축 해제된 커널 본체가 실행되어 다음 작업을 수행한다. 이 단계는 인라인 어셈블러를 포함한 어셈블리 코드가 많이 사용된다.

  • 하드웨어 로우 레벨 초기화
  • 가상 메모리 활성화를 포함한 메모리 관리 시작
  • CPU 인식 및 CPU별 특정 처리, SMP 관련 처리 실행

5. 커널 초기화 (C 코드 위주): 아키텍처에 크게 의존하지 않는 `init/main.o`[21]의 `start_kernel()` 함수가 실행되어 다음 작업을 수행한다.

이 과정을 거쳐 시스템 부팅이 완료된다.

6. 오브젝트 포맷

x86-64 아키텍처에서 vmlinux는 ELF 포맷을 따른다. 예를 들어, 젠투 리눅스 2.6.29 버전 커널의 vmlinux 파일에 GNU Binutils 패키지에 포함된 `readelf` 명령어는 ELF 파일의 헤더 정보를 출력한다[23]. 이 명령어를 실행하면 다음과 같은 ELF 헤더 정보를 확인할 수 있다. 이 정보를 통해 vmlinux가 64비트 ELF 형식(`Class: ELF64`)이며, 실행 가능한 파일(`Type: EXEC`)임을 알 수 있다.



$ readelf -h vmlinux

ELF Header:

Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00

Class: ELF64

Data: 2's complement, little endian

Version: 1 (current)

OS/ABI: UNIX - System V

ABI Version: 0

Type: EXEC (Executable file)

Machine: Advanced Micro Devices X86-64

Version: 0x1

Entry point address: 0x1000000

Start of program headers: 64 (bytes into file)

Start of section headers: 13951312 (bytes into file)

Flags: 0x0

Size of this header: 64 (bytes)

Size of program headers: 56 (bytes)

Number of program headers: 5

Size of section headers: 64 (bytes)

Number of section headers: 45

Section header string table index: 42



반면, 압축된 커널 이미지인 bzImage는 ELF 헤더를 갖지 않는 raw 바이너리 형식이므로, 동일한 `readelf` 명령어를 `arch/x86/boot/bzImage` 파일에 실행하면 아래와 같이 오류가 발생하며 ELF 파일로 인식되지 않는다.



$ readelf -h arch/x86/boot/bzImage

readelf: Error: Unable to seek to 0xc031f2eb for section headers

readelf: Error: Not an ELF file - it has the wrong magic bytes at the start


참조

[1] 웹사이트 vmlinuz Definition http://www.linfo.org[...] Bellevue Linux 2005-03-29
[2] 서적 FHS 2.3 http://www.pathname.[...] 2004-01-29
[3] 뉴스 Linux 2.6.30 https://kernelnewbie[...] 2009-06-09
[4] 뉴스 Linux 2.6.33 https://git.kernel.o[...] 2010-02-24
[5] 뉴스 Linux 2.6.38 https://kernelnewbie[...] 2011-03-14
[6] 뉴스 Linux 3.11 https://kernelnewbie[...] 2013-09-02
[7] 뉴스 Linux 5.9 https://kernelnewbie[...] 2020-10-11
[8] 메일링리스트 Re: bzImage decompression https://lkml.org/lkm[...] 1999-09-28
[9] 웹사이트 カーネル・イメージとは - Linuxキーワード https://xtech.nikkei[...] itpro.nikkeibp.co.jp 2008-02-18
[10] 문서 XFS
[11] 뉴스 2.6.30, 2.6.33, 2.6.39 커널 업데이트 2009-06-09
[12] 문서 SPARCアーキテクチャ用 arch/sparc/boot/Makefile http://git.kernel.or[...]
[13] 문서 i386アーキテクチャ用 arch/x86/boot/compressed/head_32.S http://git.kernel.or[...]
[14] 문서
[15] 문서 x86アーキテクチャ用 arch/x86/boot/compressed/misc.c http://git.kernel.or[...]
[16] Manpage objcopy
[17] 문서 x86アーキテクチャ用 arch/x86/boot/compressed/Makefile http://git.kernel.or[...]
[18] 문서 x86アーキテクチャ用 arch/x86/boot/header.S http://git.kernel.or[...]
[19] 문서 GNU Binary Utilities: objcopy http://www.bookshelf[...]
[20] 문서 Documentation/x86/boot.txt http://git.kernel.or[...]
[21] 문서 init/main.c http://git.kernel.or[...]
[22] 웹사이트 vmlinuz を解凍するための 1f 8b 08 00 http://apribase.net/[...] apribase.net 2010-02-26
[23] Manpage readelf
[24] 웹인용 vmlinuz Definition http://www.linfo.org[...] Bellevue Linux 2005-03-29
[25] 서적 FHS 2.3 http://www.pathname.[...] 2004-01-29



본 사이트는 AI가 위키백과와 뉴스 기사,정부 간행물,학술 논문등을 바탕으로 정보를 가공하여 제공하는 백과사전형 서비스입니다.
모든 문서는 AI에 의해 자동 생성되며, CC BY-SA 4.0 라이선스에 따라 이용할 수 있습니다.
하지만, 위키백과나 뉴스 기사 자체에 오류, 부정확한 정보, 또는 가짜 뉴스가 포함될 수 있으며, AI는 이러한 내용을 완벽하게 걸러내지 못할 수 있습니다.
따라서 제공되는 정보에 일부 오류나 편향이 있을 수 있으므로, 중요한 정보는 반드시 다른 출처를 통해 교차 검증하시기 바랍니다.

문의하기 : help@durumis.com