332 – Android init Process: The First Userspace Process

Series Navigation: 330-Boot Overview | 331-Bootloader | 333-Zygote

Two articles ago, we covered how the Bootloader loads the kernel. Last time, we covered how the kernel decompresses, initializes hardware, and jumps to execute userspace code.

Now we arrive at a pivotal role in the Android boot chain — init.

init is the first userspace process to run after the Linux kernel boots (PID 1). In Android, it is much simpler than the standard Linux systemd/sysvinit, but it performs several highly customized tasks:

  1. Parse and execute init.rc (configuration language)
  2. Manage the property service
  3. Load SELinux security policy
  4. Spawn Zygote

What Is init

In Linux, PID 1 is the ancestor of all processes. After completing initialization, the kernel attempts to run /sbin/init (or the init program specified on the kernel command line). If it can’t be found, the kernel panics.

Android’s init is a standalone project under system/core/init/, written in C++ and compiled into an executable:

Bash
# Android device's init
/system/bin/init
# or
/sbin/init

Its source code structure:

Bash
system/core/init/
├── init.cpp              # Main entry, parses command line, calls Parser
├── parser.cpp           # init.rc parser
├── ast.cpp              # Abstract syntax tree (Section/Trigger/Service)
├── builtins.cpp         # Built-in command implementations (mount, mkdir, write...)
├── property_service.cpp # Property service server implementation
├── selinux.cpp          # SELinux policy loading
├── devices.cpp          # Device node management (ueventd)
├── keychords.cpp        # Key chord detection (lock screen)
└── init.rc              # Main configuration file

What Is init.rc

init.rc is init’s configuration file, using a declarative domain-specific language (DSL) describing all behaviors during the boot process.

Linux’s init system (systemd) uses unit files (INI format). Android invented its own format — a trigger-based configuration language.

init.rc Basic Structure

Rc
# Part 1: Import other configuration files
import /init.usb.configfs.rc
import /init.${ro.hardware}.rc     # Device-specific configuration
import /init.trace.rc
import /init.kernel.modules.rc

# Part 2: on triggers (event-driven service startup)
on late-init
    # Trigger condition: late_initcall, kernel is ready
    trigger late-init

on late-init
    # Mount filesystems
    mount tmpfs tmpfs /sys/fs/cgroup nosuid nodev noexec
    chmod 0775 /sys/fs/cgroup
    mkdir /sys/fs/cgroup/freezer 0755 root root
    mount cgroup cgroup /sys/fs/cgroup/freezer freezer

    # Restore user data (if needed)
    exec_background /system/bin/e2fsck -f -y /dev/block/bootdevice/by-name/userdata

    # Set kernel variables
    write /proc/sys/kernel/random/boot_id ${ro.boot.serialno}

# Part 3: Service definitions
service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
    class main
    priority -20
    user root
    group root readproc
    socket zygote stream 660 root system
    onrestart write /sys/android_power/request_state wake
    onrestart restart audioserver
    onrestart restart cameraserver
    onrestart restart media
    onrestart restart netd
    writepid /dev/cpuset/foreground/tasks

# Part 4: Triggers for specific events
on property:sys.boot_completed=1
    # Boot completed notification
    bootchart stop

init’s Main Responsibilities

Bash
1. Parse and execute init.rc:
   - Read init.rc and all imported files
   - Execute on-boot triggers in order
   - Track property changes and trigger actions

2. Property Service:
   - Key-value store shared by all processes
   - /dev/__properties__ (shared memory)
   - Bionic libc reads properties via this shared memory
   - setprop/getprop commands

3. SELinux policy:
   - Load SELinux security policy at boot
   - Set security contexts for all files and processes
   - Ensure MAC (Mandatory Access Control) enforcement

4. Device node management (ueventd):
   - Listen for uevents from the kernel
   - Create device nodes in /dev
   - Set permissions and SELinux contexts

5. Service lifecycle:
   - Start core services (zygote, servicemanager, surfaceflinger)
   - Restart services on crash (onrestart)
   - Track service state (running/stopped/restarting)
Last modified: 2024年4月20日

Author

Comments

Write a Reply or Comment

Your email address will not be published.