El proceso de inicio en Android en ARM
Contents
Introducción
Android es un SO para dispositivos empotrados con pantallas táctiles. De momento nos vamos a centrar en dispositivos basados en la arquitectura ARM que como veremos, fija ya una serie de características para el arranque del sistema. Todo lo que hablaremos a partir de ahora será para Linux ARM.
Gestión del arranque
En el momento que alimentamos el sistema entra en marcha el proceso de arranque del sistema, "boot loader", que será quien finalmente tras inicializar los diferentes dispositivos que forman el sistema, terminar cargando el núcleo Linux. No vamos a entrar en todos los detalles previos al comienzo del arranque del núcleo.
Inicio del núcleo
El núcleo se comienza a ejecutar y recibe parámetros como la cantidad de memoria y su localización, el tipo de sistema, y otros parámetros adicionales que se le puedan pasar. El momento de inicio del núcleo lo podemos estudiar con adb logcat:
adb logcat
--------- beginning of /dev/log/main
I/cm ( 64): Welcome to Android 2.2 / CyanogenMod-6.0.0-N1-RC2
I/cm ( 65): _
I/cm ( 66): __ __ _ ___ _ _ __ ___ __ _ _ _ _ __ __))
I/cm ( 67): ((_ \(/'((_( ((\( ((_)((_( (('((\( ((`1( ((_)((_(
I/cm ( 68): )) _))
I/cm ( 69):
I/DEBUG ( 83): debuggerd: Jul 24 2010 18:38:25
D/AK8973 ( 90): AK8973 daemon 1.2.3 Start
D/AK8973 ( 90): (Library version : 1.2.1.620)
--------- beginning of /dev/log/system
I/Vold ( 81): Vold 2.1 (the revenge) firing up
I/Netd ( 82): Netd 1.0 starting
D/Vold ( 81): Volume sdcard state changing -1 (Initializing) -> 0 (No-Media)
D/Vold ( 81): Volume sdcard state changing 0 (No-Media) -> 2 (Pending)
D/Vold ( 81): Volume sdcard state changing 2 (Pending) -> 1 (Idle-Unmounted)
D/AndroidRuntime( 85):
D/AndroidRuntime( 85): >>>>>>>>>>>>>> AndroidRuntime START <<<<<<<<<<<<<<
I/AndroidRuntime( 85): Heap size: -Xmx16m
D/AndroidRuntime( 85): CheckJNI is OFF
D/dalvikvm( 85): creating instr width table
I/ ( 86): ServiceManager: 0xacd0
I/AudioHardwareQSD( 86): open /system/etc/vpimg success
I/AudioHardwareQSD( 86): Firmware /system/etc/vpimg size 27612
I/AudioHardwareQSD( 86): Total 27612 bytes put to user space buffer.A continuación sigue todo el inicio del núcleo Linux con montones de mensajes según va inicializando dispositivos hardware. Vemos que se accede ya en este punto a ficheros como "/system/etc/vpimg" necesarios para inicializar el audio del sistema. Este sistema de ficheros inicial está dentro del "ramdisk".
El ramdisk
El primer sistema raíz con comandos a ejecutar por parte del núcleo es el que viene en el "ramdisk". Es un disco que se copia a memoria, no hace falta tener acceso a dispositivos físicos, y por ejemplo, puede tener drivers necesarios para acceder a dispositivos de almacenamiento.
El núcleo y el ramdisk están ambos juntos dentro del fichero "boot.img" que se carga dentro del sistema ARM para llevar el arranque y que es un fichero con un formato especial y firmado. Veamos como ejemplo el que viene en CM6:
unzip -l update-cm-6.0.0-N1-RC1-signed.zip | grep boot.img 2390016 2008-02-28 21:33 boot.img unzip ../update-cm-6.0.0-N1-RC1-signed.zip boot.img Archive: ../update-cm-6.0.0-N1-RC1-signed.zip signed by SignApk inflating: boot.img split_bootimg.pl boot.img ... Writing boot.img-kernel ... complete. Writing boot.img-ramdisk.gz ... complete.
Ya tenemos tanto el kernel como el sistema de ficheros inicial ramdisk. Vamos a estudiar este:
mkdir ramdisk cd ramdisk gzip -dc ../boot.img-ramdisk.gz | cpio -i tree . |-- data |-- default.prop |-- dev |-- init |-- init.goldfish.rc |-- init.mahimahi.rc |-- init.rc |-- proc |-- sbin | `-- adbd |-- sys `-- system
Vemos que el "ramdisk" es muy sencillo y básicamente lo único que tiene es el programa "init" y "adbd" para poder entrar por adb en el sistema.
El programa init
Dentro del ramdisk está el programa "init" que es al que llama el núcleo para poner en marcha el sistema. Manual de Android init.
Como vemos de su código fuente, lo que hace a parte de crear ya algunos directorios, es interpretar los ficheros:
...
parse_config_file("/init.rc");
...
get_hardware_name();
snprintf(tmp, sizeof(tmp), "/init.%s.rc", hardware);
parse_config_file(tmp);
...El nombre del hardware lo saca de "/proc/cpuinfo". En una N1
# cat /proc/cpuinfo | grep Hardware Hardware : mahimahi
Los primeros pasos que da los encontramos en "init.rc":
head -30 init.rc | grep " "
on init
sysclktz 0
loglevel 3
# setup the global environment
export PATH /sbin:/system/sbin:/system/bin:/system/xbin
export LD_LIBRARY_PATH /system/lib
export ANDROID_BOOTLOGO 1
export ANDROID_CACHE /cache
export ANDROID_ROOT /system
export ANDROID_ASSETS /system/app
export ANDROID_DATA /data
export EXTERNAL_STORAGE /mnt/sdcard
export ASEC_MOUNTPOINT /mnt/asec
export BOOTCLASSPATH /system/framework/core.jar:/system/framework/ext.jar:/system/framework/framework.jar:/system/framework/android.policy.jar:/system/framework/services.jar
...
exec /system/bin/sysinit
class_start defaultVemos la importancia de Java en la plataforma ya que desde el inicio se define el CLASSPATH para el arranque. En este fichero se configuran parámetros del núcleo, se crean sistemas de ficheros, se configuran los permisos, se hace una configuración inicial de la red, se definen varios servicios y se inician algunos como "adbd",
En "init.rc" también es montan ya las particiones con el sistema completo, como "/system". Y se da paso al inicio habitual con los scripts dentro de "/system/etc/init.d" al ejecutar "/system/bin/sysinit".
Dentro de "init.mahimahi.rc" se inicializa todo el hardware y servicios asociados específicos del dispositivo, y se intenta configurar la wifi.
Con "class_start default" se inician todos los servicios relacionados con la clase "default", salvo aquello que tienen la opción "disabled". Todos los servicios están en la clase "default" salvo que se diga lo contrario.
De entre todos los servicios que se inician el clave es Zygote y System Manager.
Para ver todos los servicios disponibles:
# /system/bin/service list Found 52 services: 0 phone: [com.android.internal.telephony.ITelephony] 1 iphonesubinfo: [com.android.internal.telephony.IPhoneSubInfo] ... 50 media.player: [android.media.IMediaPlayerService] 51 media.audio_flinger: [android.media.IAudioFlinger]
El servicio Zygote
service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
socket zygote stream 666
onrestart write /sys/android_power/request_state wake
onrestart write /sys/poZygote es el que se encarga de lanzar la máquina virtual Dalvik por lo que ya tenemos la plataforma Java en marcha.
El servicio Service Manager
service servicemanager /system/bin/servicemanager
user system
critical
onrestart restart zygote
onrestart restart mediaEl servicio servicemanager ya actua dentro del mundo Java y se encarga ya de ir iniciando los diferentes servicios Java de Android.
En su parte de implementación Java podemos ya ver como va iniciando diferentes servicios.