Buildroot 기반 임베디드 리눅스 RootFS(Root File System) 구축 및 FHS 구조 분석
임베디드 리눅스 및 안드로이드 시스템 엔지니어링에서 파일 시스템 계층 구조 표준(FHS, Filesystem Hierarchy Standard)에 부합하는 RootFS(Root File System)를 구축하는 작업은 시스템의 안정성과 보안의 기초를 형성합니다. 부트로더(U-Boot)가 커널을 로드한 후, 커널은 가장 먼저 타겟 스토리지를 마운트하고 사용자 공간(User Space)의 첫 번째 프로세스인 init을 실행합니다.
많은 엔지니어가 Buildroot를 사용할 때 디렉터리별 역할과 가상 파일 시스템(procfs, sysfs, devtmpfs)의 동적 마운트 원리를 정확히 구분하지 못해 부팅 루프(Bootloop)나 권한 에러를 경험합니다. 본 포스팅에서는 Buildroot 환경에서 RootFS의 핵심 구조를 정확히 정의하고, ext4 마운트까지의 빌드 파이프라인을 실무 관점에서 보강합니다.
Buildroot RootFS 빌드 및 마운트 핵심 요약
- Target Architecture 설정: make menuconfig 진입 후 Target Options에서 ARM/ARM64 타겟 ABI 및 C 라이브러리(glibc, musl, uClibc)를 지정합니다.
- RootFS 이미지 포맷 지정: Filesystem images 메뉴에서 ext2/3/4 및 cpio (initramfs용) 옵션을 활성화합니다.
- 루트 파일 시스템 빌드 및 테스트: make 명령어로 빌드 후, output/images/rootfs.ext4 파일을 루프백 디바이스로 마운트하여 FHS 바이너리와 라이브러리 의존성을 검증합니다.
FHS 표준 디렉터리 구조 분석 및 Buildroot make menuconfig 설정
FHS(Filesystem Hierarchy Standard) 핵심 디렉터리 역할 비교
임베디드 리눅스 파일 시스템은 표준에 따라 엄격히 분리됩니다. 단순 저장소 디렉터리와 커널 인터페이스 가상 파일 시스템의 차이를 구별해야 합니다.
| 디렉터리 경로 | 파일 시스템 유형 | 주요 역할 및 포함 파일 종류 | 비고 |
| /bin, /sbin | Block Device (ext4, squashfs 등) | 시스템 부팅 및 관리에 필요한 필수 Executable Binary (sh, init, ip, busybox) | /sbin은 Root 권한 전용 바이너리 |
| /lib, /lib64 | Block Device | 실행 파일이 동적 링크(Dynamic Link)할 Shared Library (libc.so.6, ld-linux.so) | 아키텍처 비트 수에 맞춰 심볼릭 링크 처리 |
| /etc | Block Device | 시스템 전역 Configuration File (fstab, inittab, network/interfaces) | Static 및 Local 설정 저장 |
| /dev | devtmpfs (RAM 기반) | 하드웨어 장치 노드 파일 (ttyS0, sda, null, zero) | 커널 디바이스 드라이버 인터페이스 |
| /proc | procfs (RAM 기반) | 실행 중인 Process 정보 및 커널 런타임 정보 (/proc/cpuinfo, /proc/meminfo) | Virtual Filesystem (용량 0 Byte) |
| /sys | sysfs (RAM 기반) | 커널 내부의 Device Model, Bus, Driver 구조체 가시화 (/sys/class/net) | Hardware Control 및 Power Management |
| /var, /tmp | Block Device / tmpfs | Runtime Log, Lock 파일, Volatile Temporary Data | /tmp는 RAM 기반 tmpfs 사용 권장 |
Buildroot 설정을 통한 RootFS 이미지 생성 가이드
Buildroot의 Kconfig 환경에서 타겟 파일 시스템 포맷을 정확히 지정해야 타겟 디바이스의 storage(eMMC, NAND, NOR)에 바이너리를 기재할 수 있습니다.
# 1. Buildroot Configuration Menu Execution
make menuconfig
# Target Options
# -> Target Architecture (ARM (little endian))
# -> Target Architecture Variant (cortex-a53)
# Filesystem images
# -> [*] ext2/3/4 root filesystem
# -> ext2/3/4 variant (ext4)
# -> Exact size in KiB (65536)
# 2. Build Entire System (Toolchain, Kernel, RootFS)
make -j$(nproc)
빌드가 성공적으로 끝나면 output/images/ 디렉터리에 타겟 이미지가 생성됩니다.
# 3. Loopback Mount for Verification
mkdir -p /mnt/rootfs
sudo mount -o loop output/images/rootfs.ext4 /mnt/rootfs
# Inspect RootFS layout
ls -la /mnt/rootfs
Buildroot 기반 디버깅 및 시스템 튜닝 팁
- Busybox 바이너리 심볼릭 링크 활용:
- 임베디드 환경에서는 용량 최적화를 위해 /bin, /sbin에 위치한 대부분의 명령어 단일 바이너리인 BusyBox로 심볼릭 링크되어 있습니다. 필요에 따라 make busybox-menuconfig 명령어로 독립적인 커스텀 명령어를 세밀하게 포함하거나 제어할 수 있습니다.
- ldd 대용 cross-readelf 사용:
# Check Shared Library Dependencies on Host Machine aarch64-buildroot-linux-gnu-readelf -d /mnt/rootfs/bin/busybox | grep NEEDED - 타겟 이미지 안의 바이너리가 제대로 된 Shared Library를 참조하는지 호스트 PC에서 확인할 때 Cross Toolchain의 Readelf 도구를 사용합니다.
- 가상 파일 시스템 자동 마운트 설정:
- /etc/fstab 내에 proc, sysfs, devtmpfs가 올바르게 설정되어 있어야 부팅 중 커널 패닉을 방지할 수 있습니다.
RootFS 구축 시 자주 발생하는 실수 및 해결 방안
1. /dev 노드 미생성으로 인한 부팅 중 멈춤 현상
- 문제 원인: 커널 옵션에 CONFIG_DEVTMPFS_MOUNT가 비활성화되어 있고, RootFS의 /etc/fstab에 devtmpfs 마운트 명령이 누락된 경우 /dev/console 또는 /dev/null을 찾지 못해 Kernel Panic이 발생합니다.
- 해결 방법: Buildroot System configuration -> Path to the dev table 옵션을 정적 생성으로 쓰거나, Kernel Config에서 CONFIG_DEVTMPFS=y 및 CONFIG_DEVTMPFS_MOUNT=y를 설정해야 합니다.
2. 라이브러리 Mismatch 에러 (GLIBC_X.XX not found)
- 문제 원인: 호스트 시스템에서 컴파일한 dynamic library 파일(*.so)을 타겟 /lib에 직접 복사할 때 Cross Toolchain 버전 불일치로 발생합니다.
- 해결 방법: 손수 복사하지 않고, Buildroot 패키지 시스템(Target packages) 내에서 해당 라이브러리를 선택해 Cross Compilation 파이프라인으로 통합 빌드합니다.
결론
Buildroot를 활용한 RootFS 생성은 FHS 표준 디렉터리 이해와 가상 파일 시스템 마운트 메커니즘을 정확히 파악하는 것에서 출발합니다. 타겟 디바이스의 사양에 맞는 파일 시스템 타입(ext4, ubifs, squashfs)을 선정하고 /etc/fstab 및 Kernel Configuration을 제대로 정합함으로써 안정적인 임베디드 리눅스 시스템 환경을 구축할 수 있습니다.