Android System & AOSP Engineering/Android Automotive

안드로이드 AOSP 부팅 프로세스 완벽 분석: Bootloader, Linux Kernel, init, Zygote 및 SystemServer 구조

임베디드 친구 2026. 8. 15. 16:05
반응형

1. 안드로이드 AOSP 시스템 부팅 프로세스(Boot Process) 분석의 중요성

안드로이드 Open Source Project(AOSP) 및 차량용 안드로이드(Android Automotive OS, AAOS) 시스템 개발 시 부팅 시간(Boot Time) 최적화와 초기화 오류 디버깅은 핵심 과제입니다. 디바이스의 전원 인가(Power-On) 시점부터 애플리케이션 프레임워크(Application Framework)가 활성화되는 전 과정을 정확히 이해해야 시스템 지연 문제나 무한 부팅(Bootloop) 현상을 해결할 수 있습니다.

특히 하드웨어 제어 단계인 Bootloader, 리눅스 커널(Linux Kernel) 로딩, 사용자 공간(User Space)의 최상위 프로세스인 init, 자바 런타임 환경을 생성하는 Zygote, 그리고 핵심 서비스를 담당하는 SystemServer 간의 상호작용 구조를 이해해야 합니다. 본 가이드는 안드로이드 부팅 단계별 아키텍처와 핵심 동작 원리, 관련 소스코드 구조를 상세히 설명합니다.

2. 안드로이드 부팅 프로세스 핵심 요약 (Android Boot Sequence Summary)

  • Hardware & Kernel Phase: Power-On Reset(POR) 후 ROM/Bootloader(PBL/SBL/U-Boot)가 리눅스 커널(Linux Kernel)을 RAM에 로드하고, start_kernel() 함수를 통해 CPU/메모리 초기화 후 PID 1번인 init 프로세스를 실행합니다.
  • Native & Runtime Phase: init 프로세스는 /system/core/init에서 init.rc 스크립트를 파싱하여 Native Daemon을 실행하고, app_process 명령을 통해 Zygote 프로세스를 생성하여 ART(Android Runtime)를 초기화합니다.
  • Framework & System Service Phase: Zygote는 SystemServer 프로세스를 포크(Fork)하여 ActivityManagerService(AMS), PackageManagerService(PMS) 등 핵심 서비스를 실행하고 최종적으로 System UI 및 Launcher 앱을 화면에 출력합니다.

3. 안드로이드 부팅 아키텍처 상세 분석 및 구현 (AOSP Boot Architecture Analysis)

3.1. 하드웨어 전원 인가부터 Bootloader 및 Kernel Initialization 과정

하드웨어에 전원이 공급되면 SoC 내부의 Primary Bootloader(PBL)가 Boot ROM에서 실행됩니다. PBL은 Secondary Bootloader(SBL) 및 UEFI/U-Boot를 SRAM 및 DRAM으로 로드합니다. Bootloader는 하드웨어 검증(Verified Boot / AVB)을 수행한 후 Kernel Image(zImage/Image.gz)와 Device Tree Blob(DTB)을 RAM으로 복사하고 커널 실행 지점으로 점프합니다.

// kernel/init/main.c
asmlinkage __visible void __init __start_kernel(void)
{
    // Initialize hardware architectures, memory management, and IRQs
    setup_arch(&command_line);
    mm_init();
    sched_init();
    
    // Create the first user-space process (PID 1)
    kernel_thread(kernel_init, NULL, CLONE_FS);
}

static int __ref kernel_init(void *unused)
{
    // Execute init process from ramdisk or system partition
    if (!run_init_process("/init"))
        return 0;
    
    panic("No working init found. Try passing init= option to kernel.");
}

3.2. Native User Space Initialization: init Process 및 init.rc Parsing

kernel_init에 의해 실행된 /init 바이너리는 First-stage init과 Second-stage init 단계를 거칩니다. First-stage init에서는 VFS(Virtual File System) 마운트, devtmpfs 설정, SELinux 로딩을 처리합니다. Second-stage init에서는 init.rc 구문 분석(Parsing)을 시작합니다.

# system/core/rootdir/init.rc

# Define Zygote service triggers
service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server
    class main
    priority -20
    user root
    group root readproc reserved_disk
    socket zygote stream 660 root system
    onrestart restart audioserver
    onrestart restart cameraserver
    onrestart restart media
    onrestart restart netd
    onrestart restart wificond
    writepid /dev/cpuset/foreground/tasks

3.3. Android Runtime Activation: Zygote Process Forking 및 Preloading

init 프로세스는 app_process 바이너리를 통해 Zygote를 실행합니다. Zygote는 AndroidRuntime.cpp 내의 start() 함수를 호출하여 Dalvik/ART Virtual Machine을 생성하고, 앱 구동 시간 단축을 위해 핵심 자바 클래스 및 리소스를 메모리에 Preload합니다.

// frameworks/base/core/jni/AndroidRuntime.cpp
void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
{
    // Start the Java Virtual Machine (ART)
    JNIEnv* env;
    if (startVm(&mJavaVM, &env, zygote, primary_cpu) != 0) {
        return;
    }
    onVmCreated(env);

    // Register Android Native Functions (JNI)
    if (startReg(env) < 0) {
        ALOGE("Register of Android runtime failed\n");
        return;
    }

    // Call ZygoteInit main method in Java layer
    jclass startClass = env->FindClass(className);
    jmethodID startMeth = env->GetStaticMethodID(startClass, "main", "([Ljava/lang/String;)V");
    env->CallStaticVoidMethod(startClass, startMeth, strArray);
}

ZygoteInit.java에서는 Preloading이 완료된 후 SystemServer 프로세스를 생성하기 위한 포크 작업을 진행합니다.

// frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
public static void main(String argv[]) {
    ZygoteServer zygoteServer = new ZygoteServer();
    
    // Preload framework classes and resources
    preload(bootTimingsTraceLog);

    // Fork SystemServer process if flag is set
    if (startSystemServer) {
        Runnable runnable = forkSystemServer(abiList, socketName, zygoteServer);
        if (runnable != null) {
            runnable.run();
            return;
        }
    }

    // Run Zygote socket select loop for app creation requests
    zygoteServer.runSelectLoop(abiList);
}

3.4. Framework Core Services startup: SystemServer Initialization

SystemServer는 안드로이드 OS의 핵심 관리 서비스를 실행하는 메인 프로세스입니다. SystemServer.java의 main() 메서드가 호출되면, 내부적으로 SystemServiceManager를 생성하고 3가지 단계(Bootstrap Services, Core Services, Other Services)로 구분하여 서비스를 순차적으로 시작합니다.

// frameworks/base/services/java/com/android/server/SystemServer.java
public static void main(String[] args) {
    new SystemServer().run();
}

private void run() {
    // Load native libraries for system services
    System.loadLibrary("android_servers");

    // Initialize SystemServiceManager
    mSystemServiceManager = new SystemServiceManager(mSystemContext);

    // Start critical bootstrap services
    startBootstrapServices(t);
    // Start core system services
    startCoreServices(t);
    // Start all other application framework services
    startOtherServices(t);
}

3.5. 안드로이드 부팅 단계별 역할 및 특징 비교

부팅 단계 (Phase) 주 구성 요소 (Main Components) 실행 환경 (Execution Space) 핵심 역할 및 결과물 (Primary Function & Output)
Bootloader ROM, SBL, U-Boot, ABL Hardware / TrustZone 하드웨어 초기화, AVB 검증, Kernel & DTB 메모리 로드
Linux Kernel Kernel Image, Drivers, vmlinux Kernel Space (Ring 0) MMU/CPU 초기화, Driver Mount, PID 1 init 프로세스 포크
Init Process /init, init.rc, SELinux Native User Space (Ring 3) VFS Mount, Native Daemons 실행, Zygote 서비스 트리거
Zygote app_process, ART, JNI Java / Native Hybrid Dalvik/ART VM 생성, Common Classes/Resources Preload
SystemServer AMS, PMS, WMS, ServiceManager Framework User Space Framework Core Services 구동, Boot Completed Broadcast 전송

4. 안드로이드 부팅 디버깅 및 분석을 위한 개발 팁 (AOSP Boot Debugging Tips)

4.1. bootchart 도구를 활용한 부팅 시간 병목 분석

AOSP 빌드 환경에서 bootchart를 활성화하면 부팅 중 발생되는 CPU 및 I/O 병목 구간을 시각화할 수 있습니다.

# Enable bootchart logging in AOSP target
adb shell touch /data/bootchart/start
adb reboot

# Extract bootchart logs after reboot
tar -czf bootchart.tgz -C /data/bootchart .
adb pull bootchart.tgz

# Render bootchart image using system tool
system/core/init/grab-bootchart.py

4.2. logcat 및 dmesg 시간 표준화를 통한 부팅 로그 추적

Kernel 시간과 Android Framework 시간축을 동기화하여 특정 디바이스 드라이버 로딩 또는 서비스 생성 지연 원인을 추적합니다.

# Print kernel boot logs with timestamps
adb shell dmesg -T

# Print system logs with thread time format and boot sequence tags
adb logcat -v threadtime -b main -b system -b kernel Zygote:* SystemServer:* ActivityManager:* *:S

5. 안드로이드 부팅 프로세스 개발 시 흔히 하는 실수 (Common Pitfalls & Fixes)

5.1. SystemServer 내 블로킹(Blocking) 작업 수행으로 인한 Watchdog Crash

SystemServer에서 서비스 초기화 중 synchronous I/O 작업 또는 무한 루프가 발생하면 Watchdog가 이를 감지하여 SystemServer를 종료시키고 reboot(무한 부팅) 현상이 유발됩니다.

// INCORRECT: Blocking main thread in SystemServer service initialization
public void onStart() {
    // Direct synchronous network or disk I/O causes Watchdog trigger
    performSyncBlockOperation(); 
}

// CORRECT: Offload heavy operations to a background HandlerThread
public void onStart() {
    ServiceThread thread = new ServiceThread("MyCustomService", Process.THREAD_PRIORITY_BACKGROUND, true);
    thread.start();
    Handler handler = new Handler(thread.getLooper());
    handler.post(() -> {
        performSyncBlockOperation();
    });
}

5.2. init.rc 내 서비스 의존성 및 IPC Socket 초기화 순서 오류

Zygote 및 Native Daemon 실행에 필요한 Unix Domain Socket이나 IPC Interface가 준비되지 않은 상태에서 상위 프로세스가 구동될 경우 binder 통신 실패 오류(Binder transaction failed)가 발생합니다. init.rc 선언 시 on property: 조건절 또는 class_start 지시어를 사용하여 종속성을 보장해야 합니다.

6. 결론 (Conclusion)

안드로이드 부팅 프로세스는 하드웨어 초기화부터 리눅스 커널 로딩, Native 영역의 init 프로세스 실행, 자바 영역의 Zygote 구동 및 SystemServer 프레임워크 서비스 활성화로 이어지는 유기적인 구조를 가집니다. 각 단계의 동작 원리와 소스코드 수준의 호출 흐름을 파악함으로써, 임베디드 및 AOSP 시스템 개발 시 발생하는 부팅 지연 및 시스템 크래시 이슈를 효율적으로 분석하고 최적화할 수 있습니다.

반응형