skill/linux

Android 부팅 순서

cresent 2021. 8. 18. 10:49

<부팅 순서 분석>

안드로이드 시스템은 대략적으로 아래의 순서를 따라 부팅을 시작

- 부트로더

- 리눅스 커널

- init process

- Native daemons

- Zygote (native daemon 중 하나)

- system_server

- java 기반의 응용 프로그램

 

<안드로이드 부팅 순서 요약>

1) ROM

CPU에 전원이 인가되면, 지정 번지의 ROM code를 찾아 실행

ROM code는 Bootloader를 RAM에 적재시키는 역할을 수행

 

2) Bootloader

Ram 초기화, HW 초기화, kernel과 Ramdisk를 RAM으로 올림, kernel 시작 지점으로 Jump해서 kernel을 시작시킴

 

3) kernel

c code 실행환경 준비, kernel subsystem & device driver 초기화, rootFS mount, init process 구동

 

4) init Process

환경 변수 설정, 마운트 위치 생성, 여러 파일 시스템을 마운트, 마운트된 파일 시스템의 파일 퍼미션 설정

 

init에 의해 여러 native 데몬이 실행 (ex : service Manager, Vold, neted, ... )

 

 

 

<부팅의 시작 : primary 및 secondary 부트로더>

일반적인 Application Process의 부팅 순서

1) Primary BootLoader(PBL)로부터 부팅을 시작

2) Secondary Bootloder(SBL)를 emmc 메모리로부터 Internal Sram으로 가져와 구동시킴

3) 마지막으로 Application bootloader(LK, u-boot)가 linux kernel을 DRAM으로 가져와 부팅을 마무리

 

 

 

<Linux kernel과 Ramdisk>

Application Bootloader는 리눅스 커널과 Ramdisk Image를 eMMC로부터 읽어들여 DRAM에 적재한다.

이어서 커널의 시작 지점으로 점프하여 커널을 시작한다.

커널은 압축된 형태로 RAM으로 적재되기 때문에, 구동 시점에서는 자신의 압축을 직접 풀면서 실행하게 된다.

[커널 부팅 요약]

1) kernel과 rootfs(RAMdisk) 이미지를 RAM으로 로딩

2) LK bootloader가 kernel의 시작번지로 jump하면, kernel은 자신의 압축을 풀기 시작

3) kernel은 C code를 실행하기 위한 환경을 준비

4) kernel subsystem 초기화

5) 각종 device driver 초기화

6) Ramdisk root FS 마운트

7) init process를 구동

8) Idle 상태에서 대기

실제로 파일 시스템을 마운트하는 과정은 init process에서 하게된다.

즉, 실제 마운트 하는 곳은 kernel단이 아니라 android단 이라는 것이다.

 

 

<init process와 init.rc>

init은 kernel이 부팅의 거의 마지막 단계에서 실행시켜 주는 최초의 application process로써, 이후 모든 user space application이 init를 통해 실행되고 관리된다.

[init process 기능 요약]

init.rc, init.{hardware}.rc 처리

- Native daemon 구동

- service manager, vold, netd, rild, mediaserver, bootanimation, keystore 등 실행

SIGCHID signal 처리

child process가 죽으면 다시 살림

system property 설정

 

init rc 파일은 복수개의 action과 service로 구성되어있다.

 

[init process 흐름 분석]

1) early-init 명령을 실행

2) coldboot: ueventd가 device를 성공적으로 초기화 했는지 검사

3) property service 내부 데이터 구조를 초기화

4) keychord를 위한 핸들러를 셋업

5) 콘솔을 초기화하고, 로그 화면 혹은 문자를 출력

6) ro.serialno, ro.bashband, ro.carrier 같은 초기 속성을 설정

7) init 명령을 실행

8) early-fs 명령을 실행

9) fs 명령 실행

10) post-fs 명령 실행

11) service 명령 실행

12) SIGCHID 시그널을 받을 준비

13) service socket과 SIGCHID 핸들러가 준비되었는지를 확인

14) early-boot 명령 실행

15) boot 명령 실행

16) 모든 triggerd 명령 처리

 

ueventd는 init process가 실행시켜주는 최초의 native daemon으로, ueventd.rc와 ueventd.{hardware}.rc 파일을 토대로 각종장치 노드(/dev)를 정적으로 생성시켜 줌은 물론이고, 커널에서 동적으로 올라오는 event(kobject_uevent() 함수 호출)를 토대로 각종 장치 노드(/dev)를 동적으로 생성 및 초기화 시켜주는 역할을 담당한다.