Android Framework foundation - init process

        Android's init process is the first user space process of the Android system, and it is also the startup process of the entire system. It is an instance of the init process (process ID is 1) in the Linux system, responsible for system initialization and starting various components of the entire Android system.

        The init process is loaded and executed by the kernel when the system boots, it reads the Android init script (located in the /system/etc/init directory), and initializes the system according to the instructions in the script.

Some of the main responsibilities of Android's init process include:

1) Start and run various key services (such as Zygote, SurfaceFlinger, PackageManager, etc.) and daemon processes (such as adbd, rild, etc.).

2) Mount the file system and device nodes, and set file permissions.

3) Perform hardware initialization of each device, such as setting IO scheduling, loading hardware drivers, etc.

4) Create and start various components of the Android system, such as application process, system service process, etc.

5) Handle some events and signals during system operation, such as handling low memory, restarting the system, etc.

        In general, Android's init process plays an important role in the entire system startup process. It is responsible for coordinating and managing various components in the system to ensure that the system can be initialized and started normally.

1. Source code analysis

        First of all, the main() function is called for the entry function, but there are still some differences for different Android versions. Let's first look at the Android 9.0 version, init initialization.

1. Android 9.0 init initialization

init.cpp

Source location: /system/core/init/init.cpp

int main(int argc, char** argv) {
    bool is_first_stage = (getenv("INIT_SECOND_STAGE") == nullptr);
    // 第一次挂载
    if (is_first_stage) {
        ……
        // 挂载和创建一系列文件夹
        // 初始化Kernel日志
        InitKernelLogging(argv);
        LOG(INFO) << "init first stage started!";
        ……
    }

    // 此时,我们处于init的第二阶段。
    InitKernelLogging(argv);
    LOG(INFO) << "init second stage started!";
    ……
    // 创建一块共享的内存空间,用于属性服务
    property_init();
    ……
    // 初始化epoll功能
    epoll_fd = epoll_create1(EPOLL_CLOEXEC);
    if (epoll_fd == -1) {
        PLOG(FATAL) << "epoll_create1 failed";
    }
    // 初始化子进程退出的信号处理函数,并调用epoll_ctl设置signal fd可读的回调函数		
    sigchld_handler_init();
    ……
    // 加载default.prop文件
    property_load_boot_defaults();
    export_oem_lock_status();
    // 启动属性服务器,此处会调用epoll_ctl设置property fd可读的回调函数
    start_property_service();
    set_usb_controller();
    ……
    ActionManager& am = ActionManager::GetInstance();
    ServiceList& sm = ServiceList::GetInstance();
    // 该方法内解析init.rc文件
    LoadBootScripts(am, sm);

    // 执行rc文件中触发器为on early-init的语句
    am.QueueEventTrigger("early-init");
    // 等冷插拔设备初始化完成
    am.QueueBuiltinAction(wait_for_coldboot_done_action, "wait_for_coldboot_done");
    // ... so that we can start queuing up actions that require stuff from /dev.
    am.QueueBuiltinAction(MixHwrngIntoLinuxRngAction, "MixHwrngIntoLinuxRng");
    am.QueueBuiltinAction(SetMmapRndBitsAction, "SetMmapRndBits");
    am.QueueBuiltinAction(SetKptrRestrictAction, "SetKptrRestrict");
    // 设备组合键的初始化操作,此处会调用epoll_ctl设置keychord fd可读的回调函数
    am.QueueBuiltinAction(keychord_init_action, "keychord_init");
    // 屏幕上显示Android静态Logo
    am.QueueBuiltinAction(console_init_action, "console_init");
  
    // 执行rc文件中触发器为on init的语句
    am.QueueEventTrigger("init");

    // Repeat mix_hwrng_into_linux_rng in case /dev/hw_random or /dev/random
    // wasn't ready immediately after wait_for_coldboot_done
    am.QueueBuiltinAction(MixHwrngIntoLinuxRngAction, "MixHwrngIntoLinuxRng");

    // 当处于充电模式,则charger加入执行队列;否则late-init加入队列。
    std::string bootmode = GetProperty("ro.bootmode", "");
    if (bootmode == "charger") {
        am.QueueEventTrigger("charger");
    } else {
        am.QueueEventTrigger("late-init");
    }

    // Run all property triggers based on current state of the properties.
    am.QueueBuiltinAction(queue_property_triggers_action, "queue_property_triggers");

    while (true) {
        // 默认情况下,休眠直到有事情发生
        int epoll_timeout_ms = -1;

        if (do_shutdown && !shutting_down) {
            do_shutdown = false;
            if (HandlePowerctlMessage(shutdown_command)) {
                shutting_down = true;
            }
        }

        if (!(waiting_for_prop || Service::is_exec_service_running())) {
            am.ExecuteOneCommand();
        }
        if (!(waiting_for_prop || Service::is_exec_service_running())) {
            if (!shutting_down) {
                // 根据需要重启服务
                auto next_process_restart_time = RestartProcesses();

                // 如果有一个进程需要重新启动,及时唤醒
                if (next_process_restart_time) {
                    epoll_timeout_ms = std::chrono::ceil<std::chrono::milliseconds>(*next_process_restart_time - boot_clock::now()).count();
                    if (epoll_timeout_ms < 0) epoll_timeout_ms = 0;
                }
            }

            // 如果有更多的工作要做,马上唤醒
            if (am.HasMoreCommands()) epoll_timeout_ms = 0;
        }
        
        epoll_event ev;
        // 循环等待事件发生
        int nr = TEMP_FAILURE_RETRY(epoll_wait(epoll_fd, &ev, 1, epoll_timeout_ms));
        if (nr == -1) {
            PLOG(ERROR) << "epoll_wait failed";
        } else if (nr == 1) {
            ((void (*)()) ev.data.ptr)();
        }
    }

    return 0;
}

        Next, let's take a look at the Android 12 init initialization process.

2. Android 12 init initialization

        First of all, his initial main() function is not in init.cpp, but in main.cpp.

main.cpp

Source location: /system/core/init/main.cpp

int main(int argc, char** argv) {
#if __has_feature(address_sanitizer)
    __asan_set_error_report_callback(AsanReportCallback);
#endif
    // 稍后将恢复Boost prio
    // 设置进程的优先级
    setpriority(PRIO_PROCESS, 0, -20);
    if (!strcmp(basename(argv[0]), "ueventd")) {
        return ueventd_main(argc, argv);
    }
    
    if (argc > 1) {
        if (!strcmp(argv[1], "subcontext")) {
            android::base::InitLogging(argv, &android::base::KernelLogger);
            const BuiltinFunctionMap& function_map = GetBuiltinFunctionMap();

            return SubcontextMain(argc, argv, &function_map);
        }

        if (!strcmp(argv[1], "selinux_setup")) {
            return SetupSelinux(argv);
        }

        if (!strcmp(argv[1], "second_stage")) {
            return SecondStageMain(argc, argv);
        }
    }

    return FirstStageMain(argc, argv);
}

        This is the entry point for the entire Android system. It contains main()functions, which are the entry functions of the process. In this file, some initialization preparations are mainly carried out, and then distributed to different logic processing codes according to different command line parameters.

subcontext.cpp

Source location: /system/core/init/subcontext.cpp

int SubcontextMain(int argc, char** argv, const BuiltinFunctionMap* function_map) {
    if (argc < 4) LOG(FATAL) << "Fewer than 4 args specified to subcontext (" << argc << ")";
    
    auto context = std::string(argv[2]);
    auto init_fd = std::atoi(argv[3]);

    SelabelInitialize();

    trigger_shutdown = [](const std::string& command) { shutdown_command = command; };

    auto subcontext_process = SubcontextProcess(function_map, context, init_fd);
    // 在主循环之前恢复prio
    setpriority(PRIO_PROCESS, 0, 0);
    subcontext_process.MainLoop();
    return 0;
}

        It is about the initialization implementation of the subcontext (subcontext). In the Android system, a subcontext is an independent subprocess created and managed by the init process. Subcontexts are usually used to perform earlier tasks during system initialization, such as setting some special attributes, starting some specific services, etc.

selinux.cpp

Source location: /system/core/init/selinux.cpp

int SetupSelinux(char** argv) {
    ……
    // 挂载缺失的系统分区
    MountMissingSystemPartitions();

    // 设置 SELinux 内核日志记录。
    SelinuxSetupKernelLogging();

    // 读取策略文件
    std::string policy;
    ReadPolicy(&policy);

    // 根据需要创建辅助类
    auto snapuserd_helper = SnapuserdSelinuxHelper::CreateIfNeeded();
    ……
    // 加载 SELinux 策略
    LoadSelinuxPolicy(policy);

    ……
    // 设置 SELinux 强制执行
    SelinuxSetEnforcement();

    ……
    const char* path = "/system/bin/init";
    const char* args[] = {path, "second_stage", nullptr};
    // 执行 /system/bin/init
    execv(path, const_cast<char**>(args));
    ……

    return 1;
}

        It contains initialization logic related to the SELinux (Security-Enhanced Linux) security mechanism.

        SELinux is a security module of the Linux kernel that implements Mandatory Access Control (MAC) mechanisms. In the Android system, SELinux is widely used to strengthen the security of the system and restrict the access and operation between various processes. In this file, functions, variables, and logic related to SELinux initialization will be included. The specific implementation will depend on the version of the Android system and the requirements of the device, and it is used to configure and start the related functions of SELinux.

first_stage_init.cpp

Source location: /system/core/init/first_stage_init.cpp

int FirstStageMain(int argc, char** argv) {
    ……
}

        This is mainly the implementation of the first phase initialization of the Android system. The first stage of initialization is the stage before the init process starts running after the Linux kernel boot process (Kernel Init Process) is executed. It is only responsible for the most basic hardware initialization and file system mounting. This part of the code is actually the code of the if (is_first_stage) part in Android 9.0 above.

init.cpp

Source location: /system/core/init/init.cpp

int SecondStageMain(int argc, char** argv) {
    ……
    // 初始化Kernel日志
    InitKernelLogging(argv);
    LOG(INFO) << "init second stage started!";
    ……
    // 初始化系统属性
    PropertyInit();
    ……
    // 安装信号文件描述符处理程序
    InstallSignalFdHandler(&epoll);
    // 启动属性服务
    StartPropertyService(&property_fd);
    // 记录系统启动时间
    RecordStageBoottimes(start_time);
    // 设置 USB 控制器
    SetUsbController();
    // 该方法内解析init.rc文件
    LoadBootScripts(am, sm);

    while (true) {
        // 默认情况下,休眠直到有事情发生
        auto epoll_timeout = std::optional<std::chrono::milliseconds>{};

        auto shutdown_command = shutdown_state.CheckShutdown();
        if (shutdown_command) {
            HandlePowerctlMessage(*shutdown_command);
            shutdown_state.set_do_shutdown(false);
        }

        if (!(prop_waiter_state.MightBeWaiting() || Service::is_exec_service_running())) {
            am.ExecuteOneCommand();
        }
        if (!IsShuttingDown()) {
            auto next_process_action_time = HandleProcessActions();

            // 如果有一个进程需要重新启动,及时唤醒
            if (next_process_action_time) {
                epoll_timeout = std::chrono::ceil<std::chrono::milliseconds>(*next_process_action_time - boot_clock::now());
                if (*epoll_timeout < 0ms) epoll_timeout = 0ms;
            }
        }
  
        if (!(prop_waiter_state.MightBeWaiting() || Service::is_exec_service_running())) {
            // If there's more work to do, wake up again immediately.
            if (am.HasMoreCommands()) epoll_timeout = 0ms;
        }
  
        auto pending_functions = epoll.Wait(epoll_timeout);
        if (!pending_functions.ok()) {
            LOG(ERROR) << pending_functions.error();
        } else if (!pending_functions->empty()) {
            // 我们总是在响应其他挂起函数之前收获子函数。这是为了防止其他守护进程看到服务已经退出并要求init通过ctl重新启动它的竞争。在init获取它之前启动。
            ReapAnyOutstandingChildren();
            for (const auto& function : *pending_functions) {
                (*function)();
             }
        }
        if (!IsShuttingDown()) {
            HandleControlMessages();
            SetUsbController();
        }
    }
    return 0;
}

        Here, the main logic implementation of the init process of the Android system is mainly carried out. The init process runs as the first user space process after the Linux kernel starts, and it is responsible for initializing system services, loading device configurations, parsing init.rc files, and other system startup tasks.

Summarize

        It can be seen that Android 12 mainly splits the different functions of the main() function in the init.cpp of Android 9.0, and completes the initialization work separately.

Guess you like

Origin blog.csdn.net/c19344881x/article/details/131920906