# 마이크로 리눅스 배포판 만들기 (2023)

> Clean Markdown view of GeekNews topic #23937. Use the original source for factual precision when an external source URL is present.

## Metadata

- GeekNews HTML: [https://news.hada.io/topic?id=23937](https://news.hada.io/topic?id=23937)
- GeekNews Markdown: [https://news.hada.io/topic/23937.md](https://news.hada.io/topic/23937.md)
- Type: GN+
- Author: [neo](https://news.hada.io/@neo)
- Published: 2025-10-27T06:35:07+09:00
- Updated: 2025-10-27T06:35:07+09:00
- Original source: [popovicu.com](https://popovicu.com/posts/making-a-micro-linux-distro/)
- Points: 4
- Comments: 1

## Topic Body

- **리눅스 커널을 직접 빌드하고 최소한의 사용자 공간을 구성**하여 ‘마이크로 리눅스 배포판’을 만드는 과정을 단계별로 설명  
- **운영체제 커널의 역할**, 리눅스 배포판의 구성 요소, 그리고 커널과 사용자 공간의 관계를 기초부터 다룸  
- RISC-V 아키텍처(QEMU의 `riscv64 virt` 머신)를 예시로 사용하지만, **x86 등 다른 아키텍처에도 동일한 원리 적용 가능**  
- `init` 프로세스, `initramfs`, 그리고 Go로 작성한 간단한 셸을 포함한 **직접 실행 가능한 최소 리눅스 환경**을 구축  
- 마지막으로 `u-root` 프로젝트를 이용해 **실제 유용한 마이크로 배포판**을 만드는 방법을 소개하며, **리눅스 시스템 구조 전반의 이해를 돕는 입문 가이드**로 마무리  
  
---  
  
### 운영체제 커널이란 무엇인가  
- 커널은 **하드웨어 자원 관리와 프로그램 실행 제어**를 담당하는 운영체제의 핵심 구성 요소  
  - 단일 코어 환경에서도 여러 프로그램이 동시에 실행되는 것처럼 보이게 하는 **멀티태스킹 관리 기능** 제공  
- 커널은 **입출력 장치 제어를 추상화**하여 애플리케이션이 하드웨어 세부 주소나 레지스터 값을 직접 다루지 않도록 함  
  - 예를 들어, 프로그램은 단순히 “표준 출력에 메시지를 쓰라”고 요청하고, 커널이 실제 하드웨어와의 상호작용을 처리  
- **파일시스템 인터페이스**를 통해 고수준의 데이터 접근 방식을 제공  
  - 파일은 단순히 디스크 데이터가 아니라, 커널과 통신하는 **논리적 인터페이스**로 동작  
- 커널은 **프로세스 간 격리 및 통신 모델**을 제공하여, 각 애플리케이션이 독립적으로 실행되거나 협력할 수 있도록 함  
- **Linux 커널**은 오픈소스이며 다양한 아키텍처에서 동작 가능, 전 세계적으로 가장 널리 사용되는 커널 중 하나  
  
### 리눅스 배포판이란 무엇인가  
- 리눅스 커널만으로는 사용자가 웹 브라우저나 GUI 앱을 실행할 수 없으며, **커널 위에 여러 계층의 소프트웨어 인프라**가 필요  
- 네트워크 설정, IP 할당, VPN 관리 등은 커널이 아닌 **상위 사용자 공간 프로그램**이 담당  
- 따라서 리눅스 배포판은 **커널 + 사용자 공간 인프라의 조합**으로 정의됨  
- 배포판은 커널이 제공하는 기본 기능 위에 **패키지, 도구, 설정, 초기화 프로세스(init)** 등을 포함  
- 배포판의 복잡도는 다양하며, **Arch Linux**처럼 최소 구성부터 **Ubuntu**처럼 사용자 친화적 구성까지 존재  
  
### 커널 외부의 인프라: 사용자 공간과 `init` 프로세스  
- 커널이 부팅을 마치면 가장 먼저 **PID 1번 프로세스인 `init`** 을 실행  
  - `init`은 이후 모든 사용자 공간 프로세스의 조상으로, 시스템의 서비스와 도구를 순차적으로 실행  
- `init`이 실행하는 각종 프로세스와 도구의 집합이 **리눅스 배포판의 실질적 구성 요소**  
- 배포판이 복잡해질수록 불필요한 기능이 쌓여 **“bloated”** 하다는 비판을 받기도 함  
- 반대로, **커스텀 마이크로 배포판**을 만들면 최소한의 기능만 포함된 경량 시스템을 구축 가능  
  
### RISC-V용 리눅스 커널 빌드  
- `x86` 환경에서 **크로스 컴파일 도구체인**을 이용해 RISC-V용 커널을 빌드  
  - `kernel.org`에서 `linux-6.5.2.tar.xz` 소스 다운로드 후 `make ARCH=riscv CROSS_COMPILE=riscv64-linux-gnu- defconfig` 실행  
- `menuconfig`를 통해 커널 설정을 시각적으로 편집 가능  
- `make -j16`으로 병렬 빌드 후 `arch/riscv/boot/Image` 생성  
- QEMU에서 `qemu-system-riscv64 -machine virt -kernel arch/riscv/boot/Image`로 부팅  
  - 부팅 로그에서 **SBI 레이어 감지, UART 초기화, printk 활성화** 등의 메시지 확인 가능  
  
### 첫 번째 장애: 루트 파일시스템 없음  
- 커널 부팅 중 `VFS: Unable to mount root fs` 오류로 **커널 패닉 발생**  
  - 원인: 루트 파일시스템(`initramfs`)이 제공되지 않음  
- 파일시스템은 디스크뿐 아니라 **RAM 기반(`initramfs`)** 으로도 구성 가능  
- `initramfs`는 `cpio` 포맷으로 패키징되며, QEMU에서는 `-initrd` 옵션으로 로드 가능  
  
### `initramfs` 구축과 “Hello world” 실행  
- 최소 요구사항은 `/init` 바이너리 존재  
  - `init.c` 작성 후 정적 링크(`-static`)로 빌드  
  - `cpio -o -H newc < file_list.txt > initramfs.cpio`로 패키징  
- QEMU 실행 시 “Hello world” 출력 후 `init` 종료로 다시 커널 패닉 발생  
  - 해결: `init`이 종료되지 않도록 무한 루프 추가  
  
### Go로 작성한 간단한 셸 추가  
- `init`이 `fork`와 `execl`을 사용해 `/little_shell` 실행  
- `little_shell.go`는 사용자 입력을 받아 **명령을 에코 출력**하는 단순 셸  
  - `GOOS=linux GOARCH=riscv64 go build little_shell.go`로 RISC-V용 빌드  
- `init`과 `little_shell` 모두 UART를 통해 출력 공유  
  - 표준 입출력은 **파일 핸들로 관리**되며, `fork` 시 상속됨  
- 결과적으로 “Hello from init”과 셸 입력이 교차 출력되는 **기초 리눅스 환경 완성**  
  
### 커널의 역할 정리  
- **하드웨어 추상화**: 사용자 프로그램은 UART나 디바이스 세부 정보를 몰라도 출력 가능  
- **고수준 인터페이스 제공**: 파일시스템을 통해 다른 바이너리(`little_shell`) 접근  
- **프로세스 격리**: `init`과 셸은 독립된 메모리 공간에서 실행  
- 커널은 복잡한 하드웨어 위에서 **안정적이고 이식성 높은 실행 기반**을 제공  
  
### 운영체제의 정의  
- 커널만을 운영체제로 보기도 하고, **배포판 전체를 운영체제**로 보기도 함  
- 중요한 것은 커널과 사용자 공간의 **역할 경계와 상호작용 구조**를 이해하는 것  
  
### `u-root`로 실제 유용한 마이크로 배포판 만들기  
- [u-root 프로젝트](https://github.com/u-root/u-root)는 **Go 기반 사용자 공간 도구 세트**를 제공  
  - `u-root`는 리눅스 커널 위에서 실행되는 **사용자 공간 부트로더 및 셸 환경** 포함  
- 설치 후 `GOOS=linux GOARCH=riscv64 u-root` 명령으로 `initramfs` 자동 생성  
  - `/tmp/initramfs.linux_riscv64.cpio` 파일을 QEMU에서 실행 가능  
- 부팅 시 “Welcome to u-root!” 배너와 함께 **기본 셸 프롬프트** 제공  
  - `ls`, `pwd`, `echo` 등 기본 명령어 지원, 탭 완성 기능 포함  
  
### 네트워크 연결 실습  
- QEMU에 `virtio-net-device`와 `virtio-rng-pci` 장치 추가  
  - `-device virtio-net-device,netdev=usernet -netdev user,id=usernet` 옵션 사용  
- `u-root`의 `dhclient`로 DHCP를 통해 IP 자동 할당  
  - 예시: `eth0`에 `10.0.2.15/24` 할당  
- `wget http://google.com`으로 **외부 네트워크 접근 성공**, `index.html` 다운로드 확인  
  
### 패키지 관리자와 `init`의 중요성  
- 일반 배포판은 **패키지 관리자**를 통해 소프트웨어를 동적으로 설치·업데이트  
  - 본 실습은 임베디드형 접근으로, 전체 이미지를 재빌드해야 함  
- `init`은 단순한 프로세스 실행기가 아니라 **디바이스 초기화, 서비스 관리, 시스템 부팅 제어의 핵심 구성 요소**  
  - `u-root`의 `init` 소스코드를 통해 다양한 장치(`/dev`) 설정 과정을 확인 가능  
  
### GitHub 저장소  
- 본 가이드의 전체 코드와 예제는 [popovicu/linux-micro-distro](https://github.com/popovicu/linux-micro-distro)에서 제공  
  - `initramfs` 이미지 빌드 및 실습 재현 가능

## Comments



### Comment 45494

- Author: neo
- Created: 2025-10-27T06:35:09+09:00
- Points: 1

###### [Hacker News 의견](https://news.ycombinator.com/item?id=45703556) 
- 몇 달째 **마이크로 리눅스 배포판**을 직접 만들고 있음  
  사용자 모드는 단일 정적 바이너리 하나로 구성되어 있고, confidential microVM 컨테이너를 지원하기 위한 몇 개의 파일만 있음  
  특히 **initramfs** 구조가 흥미로움. 커널이 cpio 아카이브를 풀고 tmpfs로 진입해 /init을 실행하는 과정이 마치 마법 같음  
  여러 개의 cpio 아카이브를 이어 붙일 수도 있고, 각각 압축 가능하며 순서대로 오버레이됨  
  이 단순하면서도 우아한 설계 덕분에 직접 언팩 코드를 작성하면서 많은 걸 배움  

- 최근에는 qemu가 주요 아키텍처에서 **uftrace**를 지원하기 시작했음  
  전문가들이 “이걸 어떻게 디버깅하지?”라고 물을 때 바로 그 답이 됨  
  관련 내용은 [이 스레드](https://news.ycombinator.com/item?id=45533804)에서 참고 가능함  

- 나도 비슷한 프로젝트를 진행 중임 — [azathos](https://github.com/LevitatingBusinessMan/azathos)  
  직접 만든 **toy init**, shell, 그리고 몇 가지 유틸리티를 포함하고 있음  
  디버깅용으로 GNU coreutils를 넣었고, 지금은 프레임버퍼에 **윈도우를 그리는 기능**에 집중하고 있음  

- 이 프로젝트 정말 멋짐. 98년에 플로피 기반 “배포판”을 만들어 Windows PC 이미징을 UDP 브로드캐스트로 하던 시절이 떠오름  
  “make bzimage”, init 스크립트 오류, 무한 재부팅… 추억이 많음  
  요즘 방식도 크게 다르지 않은 게 흥미로움. **Raspberry Pi**용으로 포팅하면 재미있고 교육적일 것 같음. 직접 시도해볼지도 모름  
  - 나도 98년에 Mandrake Linux를 NetBIOS와 ISDN으로 설치하려다 **체크섬 오류** 때문에 수십 번 다시 시작했던 기억이 있음  
    결국 친구가 sftp 내용을 CD로 구워줘서 해결했는데, 그때는 2배속으로만 쓸 수 있었음  

- 이걸 **클라우드 이미지**로 (예: Vultr, DigitalOcean) 실행하거나 GUI를 띄워 Firefox를 돌리는 게 얼마나 어려울지 궁금함  
  - 클라우드 이미지로 돌리는 건 비교적 쉬움. 커널의 기본 드라이버만 있으면 되고, 이미지를 설치하면 됨  
    다른 배포판으로 부팅한 뒤 **kexec**로 자신의 커널을 실행해 메모리 상에서 설치하는 방식도 가능함  
    실제 구현 예시는 *nixos-anywhere*를 참고할 수 있음  
  - 네트워크와 스토리지를 위한 **virtio 드라이버**를 포함한 이미지를 만들고 qcow2로 변환해 DigitalOcean 등에 등록하면 됨  
    생각보다 간단한 작업임  

- 이 프로젝트를 **Raspberry Pi** 대상으로 만든 버전이 있다면 정말 흥미로울 것 같음  

- 왜 이런 걸 직접 만드는지 궁금했는데, 그냥 **Gentoo**로 리눅스를 탐구하는 건 안 되는지 생각해봄  
  - Gentoo는 “소스에서 빌드”하지만, 패키지 매니저가 대부분의 일을 대신해줌  
    사용자 공간 커스터마이징은 가능하지만, 리눅스 자체를 배우기엔 적합하지 않음  
    stage3 tarball만 봐도 이미 “미니 배포판” 수준임  

- 학습용으로는 정말 좋고, 빠르게 완성하려면 **buildroot**가 좋은 선택지임  

- 이 글 덕분에 정말 많은 걸 배움. **정보량이 풍부한 포스트**라 감사함
