Android Framework基础——init进程

        Android 的 init 进程是 Android 系统的第一个用户空间进程,也是整个系统的启动进程。它是 Linux 系统中 init 进程(进程ID为1)的一个实例,负责系统的初始化和启动整个 Android 系统的各个组件。

        init 进程在系统引导时被内核加载并执行,它会读取 Android 的 init 脚本(位于 /system/etc/init 目录下),并按照脚本中的指令来初始化系统。

Android的init进程的一些主要职责包括:

1)启动和运行各个关键服务(如Zygote、SurfaceFlinger、PackageManager等)和守护进程(如adbd、rild等)。

2)挂载文件系统和设备节点,并设置文件权限。

3)执行各个设备的硬件初始化,如设置IO调度、加载硬件驱动等。

4)创建和启动Android系统的各个组件,如应用程序进程、系统服务进程等。

5)处理系统运行过程中的一些事件和信号,如处理低内存、重启系统等。

        总的来说,Android 的 init 进程在整个系统启动过程中起着重要的作用,它负责协调和管理系统中的各个组件,确保系统能正常初始化和启动。

一、源码解析

        首先,对于入口函数都是调用 main() 函数,但对于不同的 Android 版本还是有些区别的,我们先来看一下 Android 9.0 版本的,init 初始化。

1、Android 9.0 init初始化

init.cpp

源码位置:/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;
}

        接下来我们看一下 Android 12 init 初始化流程。

2、Android 12 init初始化

        首先他的初始 main() 函数就就没在 init.cpp 中,而是在 main.cpp 中。

main.cpp

源码位置:/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);
}

        这是整个 Android 系统的入口点。它包含 main()函数,是进程的入口函数。在这个文件中,主要进行一些初始化的准备工作,然后根据命令行参数的不同分发到不同的逻辑处理代码。

subcontext.cpp

源码位置:/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;
}

        它是关于子上下文(subcontext)的初始化实现。在 Android 系统中,子上下文是由 init 进程创建和管理的一个独立的子进程。子上下文通常用于在系统初始化时执行较早的一些任务,比如设置一些特殊的属性、启动一些特定的服务等

selinux.cpp

源码位置:/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;
}

        其中包含了与 SELinux(Security-Enhanced Linux)安全机制相关的初始化逻辑。

        SELinux 是一种 Linux 内核的安全模块,用于实现强制访问控制(MAC)机制。在 Android 系统中,SELinux 被广泛用于加强系统的安全性,限制各个进程之间的访问和操作。在该文件中,会包含与 SELinux 初始化相关的函数、变量和逻辑。具体的实现会依赖于 Android 系统的版本和设备的要求,用于配置和启动 SELinux 的相关功能。

first_stage_init.cpp

源码位置:/system/core/init/first_stage_init.cpp

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

        这里主要进行 Android 系统的第一阶段初始化的实现。第一阶段初始化是在 Linux 内核引导进程(Kernel Init Process)执行后,init进程开始运行之前的阶段。它仅负责最基本的硬件初始化和文件系统挂载。这部分代码其实就是上面 Android 9.0 中 if (is_first_stage) 部分的代码。

init.cpp

源码位置:/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;
}

        这里主要进行了Android系统的init进程的主要逻辑实现。init进程是在Linux内核启动后作为第一个用户空间进程运行的,它负责初始化系统服务、加载设备配置、解析init.rc文件以及其他一些系统启动任务。

总结

        可以看到,Android 12 主要是是将 Android 9.0 的 init.cpp 中 main() 函数不同功能进行了拆分,分别完成初始化工作。

猜你喜欢

转载自blog.csdn.net/c19344881x/article/details/131920906