주제
리눅스 부팅 과정 (start_kernel함수 호출 전까지의 과정)
공부한 것
start_kernel 호출 전까지의 리눅스 부팅 과정
1. 전원 공급
- 전원이 들어오면
CPU
가ROM
에 저장된BIOS (기본 입출력 시스템)
를 불러온다. 바이오스는 전원 공급과 함께 메모리의 특정 번지에 자동 로드된다.
초기 부팅시에는 전체 메모리의 1MB 영역까지만 접근이 된다. 이 때는 protection이나 privilege는 의미가 없다.
- 바이오스가 로드되면 컴퓨터는
POST (Power-On Self Test)
테스트 후 장치들을 초기화하고, 부팅이 가능한 장치를 탐색한다. (보통 지정된 부트 드라이브로 진입한다.) Post
의 과정은 다음과 같이 흘러간다.- CPU TEST
- 기본 컨트롤러 초기화
- 키보드 초기화
- ROM BIOS 초기화
- CMOS RAM 테스트
- 메모리 테스트
- 캐시 초기화
- 인터럽트 벡터 테이블 초기화, 설치
- CMOS RAM CHECKSUM 테스트 (중복 검사의 한 종류. 오류 정정을 통해 송신된 자료의 무결성 보호)
2. 부트로더 호출
- 부팅이 가능한 장치에서
MBR (Master Boot Record)
를 찾는다. 보통MBR
은 디스크의 첫 번째 섹터에 위치하며, 부트로더가 저장되어 있다. - Boot Code 부팅 가능한 파티션을 찾아 해당 파티션의 부트 섹터를 호출
- Partition Table 파티션의 정보가 포함되어 있음, 총 4개
- Signature 섹터의 오류 유무를 확인
- 리눅스의
GRUB
은 Windows의active partition
으로 처리되지 않고, 다음과 같은 순서를 따른다. - MBR 자체에
bootloader
을 내장하고 있다. (GRUB
에서는 stage 1) - MBR의 크기는 작기 때문에, 추가 부트스트랩 코드가 포함된 디스크에서 코드를 로드한다.
- 로드한 부트스트랩 코드와 MBR의 부트 코드가 부트 로더의 두 번째 단계가 포함된 파일을 읽는다. (
GRUB
에서는 stage 2) - 부트 로더 코드는 이제 커널 이미지를 로딩한다. 이를 위해 파일 시스템에 대한 정보를 갖고 있어야 하므로, Linux에서는
vmlinuz-x.x.x-version
과 같은 바이너리를 디스크로부터 읽어온다.
부트스트랩
: 매우 간단하고 작은 코드, 부팅 가능한 장치로부터 부트로더를 로드하고 실행하는 역할이 두 번째 단계 코드는 부팅 구성 파일 (
GRUB
의 grub.conf
)을 읽어온다.3. 부트로더(GRUB)로 커널 이미지 로딩
- 커널 이미지는 결국 부트로더에서
BIOS disk I/O Service
를 이용해 메모리로 로딩된다.
→
/boot/vmlinux-x.x.x-version
과 비슷한 이미지를 디스크에서 읽어와 복사본으로 올린다.arch/x86/boot/compressed/head_32.S
를 호출해서startup_32
함수를 실행합니다.
/* * These symbols needed to be marked as .hidden to prevent the BFD linker from * generating R_386_32 (rather than R_386_RELATIVE) relocations for them when * the 32-bit compressed kernel is linked as PIE. This is no longer necessary, * but it doesn't hurt to keep them .hidden. */ .hidden _bss .hidden _ebss .hidden _end __HEAD SYM_FUNC_START(startup_32) cld cli
이전 리눅스 버전?
여기서부턴 예전 리눅스 버전..?
arch/i386/boot/setup.S
에서 커널 이미지가 호출되어,start()
함수가 실행된다.
→ 기본적인 하드웨어 수정 작업을 거친다.
→
arch/i386/boot/compressed/head.S
의 startup_32()
함수 호출startup_32()
함수는 스택 설정,BSS(Block Started by Symbol
을 초기화
→
arch/i386/boot/compressed/misc.c
내의 decompress_kernel()
함수를 호출해 압축된 커널을 해제→
arch/x86/kernel/head_32.S
에 위치하는듯 함startup_32()
함수의 기능- 하드웨어의 종속적인 초기화
- 세그먼트 값들 설정
- 페이지 테이블 초기화
- IDT 설정
- CPU 유형 검사, FPU 검사
- GDT와 IDT 로딩
start_kernel()
호출
// arch/alpha/boot/bootp.c /* * Start the kernel. */ static inline void runkernel(void) { __asm__ __volatile__( "bis %0,%0,$27\n\t" "jmp ($27)" : /* no outputs: it doesn't even return */ : "r" (START_ADDR)); } extern char _end; #define KERNEL_ORIGIN \ ((((unsigned long)&_end) + 511) & ~511)
참고 문헌
예전 레거시, 요즘은 UEFI 바이오스
왜 커널을 압축했을까? (커널을 빌드할때 압축됨)
→ 압축 안하면 꽤큼, 그래서 메모리에 올릴 수 있게됨
KERNEL-IMAGE-SIZE : 1GB
압축을 했을때 1GB?
/arch/x86/include/asm/page_64_types.h
댓글