-
임베디드 시스템이란? & 리눅스 부팅 시퀀스 (부트로더 -> 커널 -> init)임베디드 개발 환경 이야기 2025. 9. 15. 12:08
차량 전장 시스템 SW 개발자로 커리어를 시작하며, 앞으로 배우고 성장할 내용들을 블로그에 기록해보기로 했습니다.
그 첫 번째 주제는 모든 것의 기반이 되는 '임베디드 시스템'과 '리눅스 부팅 과정'입니다.
컴퓨터공학을 전공했지만, 특정 목적을 위해 만들어진 하드웨어와 그 위에서 동작하는 소프트웨어를 다루는 것은 또 다른 세계인 것 같습니다.
저처럼 이 분야에 첫발을 내딛는 분들께 도움이 되길 바라며, 제가 이해한 내용을 최대한 쉽고 자세하게 풀어보겠습니다.
Part 1. 임베디드 시스템(Embedded System)이란 무엇일까요?
우리가 매일 사용하는 데스크톱 PC나 노트북은 '범용(General-Purpose)' 컴퓨터입니다.
워드 작업, 게임, 영상 시청, 코딩 등 사용자가 원하는 다양한 작업을 할 수 있죠.
반면, 임베디드 시스템은 '특정한 기능'을 수행하기 위해 만들어진 컴퓨터 시스템입니다.
마치 '범용 칼'이 아닌 '과도', '회칼'처럼 정해진 목적에 최적화되어 있습니다.제가 앞으로 다루게 될 자동차의 AVN(Audio, Video, Navigation) 시스템이 대표적인 예입니다. 음
악을 틀고, 영상을 보여주고, 길을 안내하는 '정해진' 임무를 수행하죠.쉽게 비유하자면,
- 일반 PC: 무엇이든 담을 수 있는 '백팩'
- 임베디드 시스템: 카메라와 렌즈만 안전하게 보관하기 위한 '카메라 전용 가방'
일반 PC와 임베디드 시스템의 차이점을 표로 정리하면 더 명확하게 이해할 수 있습니다.
구분 범용 시스템 (PC, 노트북) 임베디드 시스템 (AVN, 세탁기, 공유기) 목적 다양하고 일반적인 목적 (문서작업, 게임, 웹서핑 등) 특정하고 제한된 목적 (음악 재생, 경로 안내, 세탁 등) 하드웨어 표준화된 부품 사용, 쉬운 확장 (RAM, 그래픽카드 교체) 목적에 최적화된 하드웨어 (SoC), 확장이 어렵거나 불가능 소프트웨어 사용자가 OS나 응용 프로그램을 자유롭게 설치/삭제 미리 정해진 OS와 소프트웨어가 펌웨어 형태로 탑재 핵심 고려사항 높은 성능, 확장성, 범용성 안정성, 실시간성, 저전력, 제한된 자원(비용) 임베디드 시스템 개발자가 기억해야 할 특징
따라서 임베디드 시스템 개발, 특히 '성능과 안정성'을 담당하는 개발자는 다음과 같은 특징을 항상 염두에 두어야 합니다.
- 제한된 자원 (Resource Constraints):
- AVN 시스템은 PC처럼 CPU 성능이 아주 높거나 메모리(RAM)가 넉넉하지 않습니다.
정해진 하드웨어 사양 안에서 최고의 성능을 내야 합니다.
메모리 누수(Memory Leak)나 비효율적인 CPU 사용은 시스템 전체의 안정성을 해치는 치명적인 결함이 될 수 있습니다.
- AVN 시스템은 PC처럼 CPU 성능이 아주 높거나 메모리(RAM)가 넉넉하지 않습니다.
- 높은 안정성과 신뢰성 (High Stability & Reliability):
- PC에서 프로그램이 멈추면 그냥 껐다 켜면 되지만, 자동차가 주행하는 중에 내비게이션이 멈추거나 후방 카메라가 나오지 않는다면 큰 사고로 이어질 수 있습니다.
시스템은 어떤 상황에서도 안정적으로 동작해야 합니다.
- PC에서 프로그램이 멈추면 그냥 껐다 켜면 되지만, 자동차가 주행하는 중에 내비게이션이 멈추거나 후방 카메라가 나오지 않는다면 큰 사고로 이어질 수 있습니다.
- 실시간성 (Real-time Constraints):
- 'Hard' 실시간까지는 아니더라도, 운전자가 브레이크를 밟았을 때 관련 정보가 즉시 화면에 표시되거나, 후진 기어를 넣었을 때 1~2초 안에 후방 카메라 화면이 떠야 합니다.
이처럼 정해진 시간 안에 반드시 반응해야 하는 요구사항이 많습니다.
'부팅 시간 최적화'가 중요한 이유이기도 합니다.
- 'Hard' 실시간까지는 아니더라도, 운전자가 브레이크를 밟았을 때 관련 정보가 즉시 화면에 표시되거나, 후진 기어를 넣었을 때 1~2초 안에 후방 카메라 화면이 떠야 합니다.
Part 2. 리눅스는 어떻게 잠에서 깨어날까? 부팅 시퀀스 A to Z
자, 그럼 우리가 개발할 소프트웨어가 올라가는 이 임베디드 시스템 보드는 어떻게 잠에서 깨어나 우리가 아는 리눅스 화면을 보여줄까요?
전원 버튼을 누르는 그 순간부터 운영체제가 모든 것을 제어하기까지의 과정을 '부팅 시퀀스(Booting Sequence)'라고 합니다.쉽게 비유하자면,
우리가 아침에 일어나서 정신을 차리고, 오늘 할 일을 시작하는 과정과 똑같습니다.- (알람 소리) 전원 ON!
- (눈 뜨고 잠 깨기) 부트로더
- (정신 차리기) 커널 로딩
- (오늘 할 일 시작) init 프로세스 실행
이제 각 단계를 조금 더 자세히 들여다보겠습니다.
1단계: 전원 ON & 부트로더 (The Bootloader)
전원 ON -> ROM 코드 실행 -> 부트로더 실행
전원이 공급되면 CPU는 정해진 메모리 주소(Reset Vector)에 있는 아주 작은 프로그램을 실행합니다.
이 프로그램은 보통 부트로더(Bootloader)를 찾아 메모리에 올리고 실행시키는 역할을 합니다.
임베디드 시스템에서는 주로 U-Boot(Universal Bootloader)가 사용됩니다.부트로더의 역할: "아침에 일어나 가장 먼저 할 일을 알려주는 비서"
- 하드웨어 초기화: 잠에서 덜 깬 우리 몸(하드웨어)의 주요 장기들이 제대로 움직이는지 기본적인 점검을 합니다.
CPU, 메모리(DRAM), 저장장치(eMMC, SD카드) 등을 인식하고 최소한으로 사용 가능하게 만듭니다. - 커널 이미지 로딩: 오늘의 두뇌 역할을 할 '리눅스 커널' 파일을 저장장치에서 읽어와 메모리(RAM)의 특정 위치에 올려놓습니다.
- 커널에 부팅 인자 전달: 커널에게 "오늘 일은 이런이런 조건에서 시작해야 해!"라고 알려주는 쪽지를 전달합니다.
예를 들어, "루트 파일 시스템은 저기 저장장치의 두 번째 파티션에 있어" 라거나 "화면 해상도는 1920x1080으로 설정해줘" 같은 정보들입니다. - 커널 실행: 모든 준비가 끝나면, 메모리에 올려둔 커널의 시작점으로 점프하여 CPU의 제어권을 커널에게 넘겨줍니다.
이제 부트로더의 임무는 끝납니다.
2단계: 운영체제의 심장, 커널 (The Kernel)
부트로더가 커널 실행 -> 커널 초기화 -> init 프로세스 실행
이제 제어권을 넘겨받은 커널이 본격적으로 시스템을 깨우기 시작합니다. 마치 우리 뇌가 완전히 깨어나 몸의 모든 부분을 제어하기 시작하는 것과 같습니다.커널의 역할: "잠에서 완전히 깨어난 뇌"
- 자기 자신 초기화: 부트로더가 올려준 커널 이미지는 보통 압축되어 있습니다.
커널은 먼저 자신의 압축을 풀고, 본격적인 초기화 코드를 실행합니다. - 시스템 하드웨어 초기화: 부트로더가 했던 최소한의 초기화에 이어, 커널은 시스템의 모든 장치를 제어하기 위한 본격적인 초기화를 시작합니다.
이때 디바이스 트리(Device Tree)를 참조하여 보드에 연결된 모든 하드웨어(사운드 칩, 네트워크 칩, 화면 등)를 인식하고, 해당 장치를 제어할 디바이스 드라이버를 초기화합니다. - 메모리 및 프로세스 관리자 준비: 시스템의 메모리를 어떻게 사용할지 계획하고, 여러 프로그램(프로세스)들을 어떻게 공평하고 효율적으로 관리할지 스케줄러를 준비시키는 등, 운영체제의 핵심 기능들을 활성화합니다.
- 루트 파일 시스템 마운트: 부트로더에게 전달받은 정보를 바탕으로, 운영체제의 모든 파일이 들어있는 루트 파일 시스템(Root Filesystem)을 저장장치에서 찾아 마운트합니다.
이제 ls, cd 같은 명령어를 사용할 수 있는 기반이 마련된 것입니다. - init 프로세스 실행: 모든 준비가 끝나면, 커널은 파일 시스템에서 /sbin/init 이라는 프로그램을 찾아 실행합니다.
이 init 프로그램이 바로 사용자 공간(User Space)에서 실행되는 최초의 프로세스이며, 지금부터 실행되는 모든 다른 프로세스들의 조상이 됩니다.
3단계: 모든 프로세스의 시작, init (The First Process)
커널이 init 실행 -> 시스템 서비스들 실행 -> 부팅 완료
init 프로세스는 항상 프로세스 ID(PID) 1번을 부여받습니다.
이 프로세스의 역할은 시스템 운영에 필요한 각종 배경 서비스(데몬, Daemon)들을 순서대로 실행시켜 부팅을 마무리하는 것입니다.init의 역할: "오늘의 할 일 목록(To-do list)을 보고 하나씩 실행하는 나"
init은 미리 정해진 설정 파일을 읽어 시스템에 필요한 서비스들을 실행합니다.
네트워크 연결을 위한 network
시스템 로그를 기록하는 journald (또는 syslogd)
화면에 그래픽 유저 인터페이스(GUI)를 띄우기 위한 weston 또는 surfaceflinger(안드로이드)
AVN의 메인 애플리케이션 등
과거에는 SysVinit이라는 방식이 순차적으로 스크립트를 하나씩 실행해서 부팅이 느렸지만, 요즘은 systemd라는 현대적인 init 시스템을 주로 사용합니다.
systemd는 서비스들을 병렬로 실행하고 의존성을 효율적으로 관리하여 부팅 속도를 획기적으로 개선했습니다.모든 서비스가 성공적으로 실행되면, 드디어 우리는 내비게이션 화면을 보거나 라디오를 들을 수 있게 됩니다.
이것으로 기나긴 부팅 과정이 끝납니다.정리하며
오늘 우리는 임베디드 시스템이 무엇이며, 이 시스템이 어떤 과정을 거쳐 부팅되는지 알아보았습니다.- 임베디드 시스템: 특정 목적을 위해 하드웨어와 소프트웨어가 최적화된 컴퓨터 시스템.
- 부팅 시퀀스:
- 부트로더: 하드웨어를 최소한으로 깨우고, 커널을 메모리에 올려 실행시킨다.
- 커널: 시스템의 모든 하드웨어를 제어할 준비를 마치고, 최초의 사용자 프로세스인 init을 실행시킨다.
- init (systemd): 시스템 운영에 필요한 서비스들을 실행시켜 부팅을 완료한다.
이러한 기본적인 동작 원리를 이해하는 것은 '성능과 안정성'을 책임지는 개발자에게 매우 중요합니다.
부팅이 왜 느린지, 부팅 과정에서 왜 시스템이 멈추는지 원인을 파악하려면 이 흐름을 꿰뚫고 있어야 하기 때문입니다.
다음 포스팅에서는 이 흐름 속에서 등장했던 BSP(Board Support Package) 와 커널에 대해 좀 더 깊이 파고들어 보겠습니다.'임베디드 개발 환경 이야기' 카테고리의 다른 글
커널(kernel)이란? 시스템의 지배자, 리눅스 커널(Kernel)의 모든 것 (0) 2025.09.15 BSP란? 임베디드 시스템의 통역사 BSP 파헤치기 (0) 2025.09.15 [리눅스 기초] Makefile이란? 똑똑한 빌드 자동화 (0) 2025.09.12 [Yocto 기초] Yocto란? 핵심 개념(BitBake, Layer, Recipe) 쉽게 이해하기 (0) 2025.09.12 [Gerrit 기초] Gerrit이란? GitHub의 Pull Request와 비교 (0) 2025.09.12