All Articles

Linux Boot Loader

Linux GNU

Image Source : Redbubble.com

시스템 파워 버튼을 누른 다음 리눅스에서는 어떠한 일이 일어날까?

Boot Loader

부트로더는 OS를 부트 시킬때 실행되는 프로그램이다. 즉 가장 먼저 실행되는 프로그램이라 할 수있다. 부트로더는 하드웨어 의존성이 강하기에 각각의 OS별로 다른 부트로더들이 사용된다. 우리는 리눅스의 부트로더에 대해 알아볼 것이다.
* boot : 컴퓨터에 리셋을 발생시켜 새롭게 컴퓨터를 기동시키는 작업 | 전원을 누르는 순간부터 바탕화면이 뜨는 그 순간까지를 의미

만약 컴퓨터에 단 하나의 OS만 존재한다면 부트로더는 해당 커널을 로드하기만 하면 된다. 하지만 여러 OS가 설치되어있거나 다양한 커널이 설치되어 있다면 컴퓨터는 그 중에 어떤 것(OS든 커널이든)을 사용할것인지 우리가 선택하도록 해준다. 부트로더는 운영체제가 실행되기 전에 필히 먼저 실행되야 하는 프로그램으로써 커널이 올바르게 작동될 수 있도록 모든 관련 작업들을 처리한다.

기능

부트로더의 기능은 아래와 같다.

  • 초기화 : 메모리, 하드웨어, 직렬포트, 네트워크, 프로세서 속도, 인터럽트
  • 적재 및 실행 : Kernel, RAM
  • UI : 사용자 인터페이스 기능

6가지 스탭

리눅스의 부트로더는 총 6가지(BIOS 부터 Runlevel까지)의 스탭으로 나뉜다. 각각의 스탭은 아래와 같다.

Step of Bootloader

이 여섯가지의 Boot process의 과정을 배움으로써 리눅스에서 발생한 문제를 해결할수 있는 능력이 상승할 것이다. 또한 리눅스 작동원리에 대한 이해력이 높아진다. 스탭별로 어떠한 작업이 이루어지는지 자세히 알아보자.

BIOS

BIOS: Basic Input Output System
파워 버튼을 누르면 파워 서플라이가 전기가 공급되는지 확인을 한 후에 BIOS로 "Power Good" 이라는 신호(+5 volts signal)를 보내게 된다. 이 과정은 보통 0.1초에서 0.5초 정도 소요된다. Power Good Signal 그 후, Boot Process의 첫번째 과정인 BIOS 프로그램이 실행된다. BIOS는 이름이 의미하듯이 모든 데이터의 입출력을 제어하여 주는 프로그램이다. BIOS가 시작되면서 키보드, 스크린을 포함한 하드웨어를 초기화하고 설정한다. 이 과정을 POST(Power On Self Test)라고 한다. Test가 진행되며 여러 요소들을 체크 한 후 POST 과정을 모니터에 출력시킨다. 테스트 내용으로는 System Bus, RTC(Real-Time Clock), 그래픽 카드, 키보드 동작, RAM등이 있다. 화면에 관련 정보인 BIOS, Mainboard, CPU, 메모리 용량 등이 표시된다. 이 이후 과정은 OS가 주관하게 된다.
* BIOS는 마더보드에 장착되어 있는 ROM 칩에 저장되어 있다.
* POST (시동 자체 시험) :BIOS가 CPU에게 POST 작업을 지시한다.

MBR

MBR : Master Boot Record
POST가 완료되면, 시스템 컨트롤은 BIOS를 부트로더에 옮긴다. 대부분의 경우 부트로더는 하드디스크에 담겨있다. OS를 실행시키기 위해 하드디스크에 저장되어진 정보를 읽어들여야 하는데 이 정보는 MBR에 저장되어 있다. MBR은 기억장치의 512 bytes 저장공간이다.
* 리눅스가 부팅이 안되는 상황은 MBR이 제거된 경우에도 벌어진다. 이럴때는 지워진 MBR을 다시 복구해야 한다.

Sector

MBR이 위치한 곳은 기억장치에서 첫번째 섹터(Sector)이다. MBR에는 부팅을 하기 위한 정보를 갖고 있다. MBR은 GRUB 부트로더를 적재시키고 실행한다.
* Sector: 하드디스크에서 주소 지정을 할 수 있는 최소의 단위 | 섹터단위로 데이터를 읽거나 기록 ( 섹터 하나당 512 바이트 기록 가능)

MBR loads GRUB

MBR은 세 가지 구성요소인 부트코드 (446 bytes), 파티션 테이블 (64 bytes), 시그니쳐 (2 bytes)로 이루어져 있다. 512 bytes가 어떠한 정보로 이루어져 있는지 살펴보자.
* 리눅스에서 부트로더는 GRUB 외에도 다양하다. 다른 종류로는 ISOLINUX (이동식 매체로 부터 부팅 될 때), DAS U-Boot (embedded 디바이스로부터 부팅 될때) 등이 있다.

MBR Structure MBR Partition Table

  1. Boot Code 부트코드 (446 bytes)
  2. 부팅을 하기 위한 정보가 담겨 있다.
    실행될 코드와 에러 메시지가 저장되어 있다.
  3. Partition Table 파티션 테이블 | 분할표 (64 bytes)
  4. 파티션에 관한 정보가 담겨 있다.
    부팅에 필요한 정보가 있는 파티션으로 점프시켜주기 위한 정보.
    총 네개의 파티션으로 나뉘어져 있다. (4 * 16)
    OS는 파티션을 단위로 하여 디스크를 처리한다.
    10진수
    16진수
    About
    Byte(s)
    0

    0x0000
    Boot Indicator
    부팅 가능시 : 0x80 | 부팅 불가시 : 0x00
    해당 파티션이 부팅 가능한 파티션인지 아닌지를 표시
    1
    1~3

    0x0001~0x0003
    Starting CHS Address
    CHS의 시작 주소.
    CHS 주소를 사용할 경우 0:06CA 으로 점프.
    부팅 가능한 파티션의 첫 섹터를 읽어 메모리 0:7c00에 덮어쓴다.
    3
    4

    0x0004
    Partition Type
    파티션의 종류.
    1
    5~7

    0x0005~0x0007
    Ending CHS Address
    3
    8~11

    0x0008~0x000B
    Starting LBA Address
    LBA의 시작주소. 파티션의 시작 위치이다.
    LBA 주소를 사용할 경우 0:06E6 으로 점프.
    부팅 가능한 파티션의 첫 섹터를 읽어 메모리 0:7c00에 덮어쓴다.
    4
    12~15

    0x000C~0x000F
    Total Sectors
    파티션의 총 색터 개수
    4
    * 리눅스는 최소 두 개 이상의 파티션을 필요로 한다.
    * Partition : 저장장치 내에서 나뉘어진 연속된 논리적 저장공간을 의미한다. 여러개의 파티션으로 나뉜다면 각각의 파티션은 드라이브로 인식된다. 저장공간을 나눔으로써 효율적이며 안전하게 데이터를 관리할 수 있게 된다.
    * 파티션 설정 방법은 MBRGPT(GUID Partition Table)두 가지로 나뉜다. 대부분의 OS는 더 오래된 방법인 MBR(1983)을 사용한다. 둘의차이점에 대해 알고싶다면 여기에서 확인하도록 하자.
  5. Signature
  6. 해당 섹터의 오류 확인에 관한 값의 정보
    기본값은 0xAA55 이다.
    값이 0xAA55로 뜨게 된다면 BIOS는 시스템 부팅을 시작한다. 만약 0x0000 값이 뜬다면 '부팅 가능한 디스크를 찾지 못했다'는 의미이기에 BIOS로부터 에러메세지를 받게 된다.

Bootloader in Action

부트로더(MBR)는 partition table을 검사하며 부팅가능한 파티션을 찾는다. 부팅 가능한 파티션을 찾아낸 후에는 두번째로 진행되야 할 부트로더(GRUB)를 찾는다. MBR 은 다음 스탭인 GRUB 를 RAM에 적재시킨 후 실행시킨다.

GRUB

GRUB : Grand Unified Bootloader
리눅스에서 사용하는 부트로더는 LILO (LInux LOader) 와 GRUB 가 있다. 두 방법 모두 싱글유저모드로 부팅하는 기능을 제공해준다. 만약 옛날 리눅스를 사용한다면 LILO 방법을 이용하고 있을 것이다. 현재는 대부분 GRUB를 사용하고 있기에 우리는 GRUB를 알아볼 것이다. GRUB는 GNU에서 만든 부트로더이다.
* GNU 가 무엇인지 모른다면 이전 포스팅을 참고하자.
* LILO와 GRUB 에 대한 차이점을 자세히 알아보고자 한다면 여기를 통해 공부해보자.

GRUB를 통해 대부분의 OS 커널을 불러올 수 있다. 아래와 같은 기능을 지원한다.

  • 사용자 정의 부팅 기능
  • 파일 시스템 직접 접근 기능
  • 다양한 실행 파일 형식 지원
  • BSD FFS, FAT16, FAT32, Minix, and ext2 etc
  • 비 멀티부팅 운영 체제 지원
  • Multiboot을 지원하지 않는 OS(Linux, FreeBSD, NetBSD, and OpenBSD etc)를 chain-loading을 통해 지원해준다. 체인로딩은 PC BIOS 또는 EFI (Extensible Firmware Interface) 플랫폼에서만 지원이 된다.
    * Chian-loading 에 관한 자세한 정보는 여기에서 알아볼 수 있다.
  • 메뉴 인터페이스 제공
  • 다양한 파일 시스템 지원
  • 자동으로 압축 해제 지원
  • gzip
  • 모든 RAM을 BIOS와 관계 없이 인식
  • LBA 및 네트워크 지원
  • 디스크 없는 시스템 지원
  • 사람이 읽을 수 있는 설정 파일 제공

BIOS가 부팅 장치를 찾고 MBR을 읽어온 후 GRUB 의 첫번째 스테이지는 MBR 에서 시작된다. 이 후 GRUB 에 위치한 stage 1.5 를 불러들인다. root 디스크의 특정 위치로 부터 stage 2를 불러들여 실행시킨다. 그로인해 메뉴나 명령 프롬프트가 화면에 출력이 된다. LILO 와 비교하였을때 GRUB 가 가지는 가장 큰 특징은 GRUB 는 커널의 물리적인 위치를 알 필요가 없다는 것이다. 즉, 파일명과 커널이 위치하고 있는 파티션만 안다면 커널을 로드할 수 있다. 파일명이 바뀌지 않는이상 매번 GRUB를 실행해 주지 않아도 된다. GRUB 실행 화면을 통해 어떤 커널(두 개 이상 사용시)을 로딩할 것인가를 선택할 수 있다.
* GRUB를 설치하고자 한다면 이곳에서 다운 가능하다.
* Debian 을 사용하는 경우라면 # apt-get install grub 의 명령어만 입력하면 된다.

Kernel

OS 의 핵심이 되는 부분.
가상 메모리, 하드웨어 입출력 자원관리, 시스템 동작, 보안등을 제어해준다.

다음 작업으로써는 리눅스 커널과 initramfs(initial RAM-based file system) 가 메모리에 적재된다. GRUB 부트로더가 Kernel의 이미지를 읽어서 부팅시킨다. 리눅스 커널은 bzImage (Big Zimage) 의 형태를 띄고 있다. 이 이미지는 커널이 컴파일 되는 동안 생성 된다. 관련 명령어는 make bzImage 이다. bzImage는 부트섹션, 셋업코드, 커널이미지로 구성되어 있다. 셋업코드는 하드웨어 장치를 해당 리눅스 커널에 맞게 초기화 작업을 진행한다. setup() 에 관한 작업 내용은 아래와 같다.

  • 키보드 반복 간격과 속도의 설정
  • VGA 초기화
  • 디스크 컨트롤러 초기화
  • PS/2 장치 검사
  • APM (Advanced Power Management) 과 EDD (Enhanced Disk Drive) 의 BIOS 지원 여부 검사
  • FPU (Floating Point Unit) 초기화 (FPU가 존재할 경우에만)
  • PIC (Programmable Interrupt Controllers) 를 다시 프로그래밍 한 후 모든 인터럽트 마스크
  • ...etc

이 후 strtup_32() 에 해당되는 작업이 시작된다. 레지스터와 임시 스택을 초기화 시켜주는 작업이 이루어진다. 상기 두 명령어에 해당하는 작업이 끝나면 커널이 실행된다. 작업 명령어는 start_kernel 이다.
* 커널의 동작에 관해 더 자세히 알고자 한다면 여기에서 세부 내용을 공부해보도록 하자

Anatomy of bzImage

Init

커널이 셋업이 완료된 후에 커널은 시스템 초기화 작업인 /sbin/init 을 수행시킨다. 이로써 리눅스 유저를 위한 환경이 준비가 된다. 그 다음은 /etc/rc.d/rc.sysinit 으로써 환경 경로, 스왑 시작, 파일 시스템 확인등에 관한 작업이 진행된다. 초기화에 관한 작업이 모두 수행된 후에는 마지막 스탭인 Runlevel 프로그램이 수행된다.

Init

Runlevel

이 부분에서는 /etc/rc.d/rc*.c 에 관한 작업이 수행된다. 여러 가지로 분류되어 있는데 시스템을 어떤 방식으로 부팅할 것인가에 관한 것이다. Runlevel의 종류는 아래와 같다. 현재의 진행중인 runlevel에 관한 정보를 알고 싶을때 사용하는 명령어는 #who -r이다.

Runlevel
Mode | Directories
Action
0
Shutdown
/etc/rc.d/rc0.d/
Shuts down system
1
Single-User Mode
/etc/rc.d/rc1.d/
Maintenance mode
2
Multi-User Mode
/etc/rc.d/rc2.d/
Does not configure network interfaces
3
Multi-User Mode with Networking
/etc/rc.d/rc3.d/
Starts the system normally with all the services(Text mode interface)
4
N/A
/etc/rc.d/rc4.d/
Not used
5
X11
/etc/rc.d/rc5.d/
As runlevel 3 + GUI
6
Reboot
/etc/rc.d/rc6.d/
Reboots the system

이로써 bootloader의 6가지의 스탭들을 알아보았다. 각각의 스탭별로 더 자세한 내용을 공부하고자 한다면 아래 reference에 정리해둔 링크를 참고하도록 하자. 다음 포스팅에서는 커널에 대해 자세히 알아보고 한다.

Reference