android-init

本文主要介绍init 过程, 下面三张图,基本覆盖了核心点


Init main 流程
SIGCHLD流程
options 执行流程

对system/core/init/init.cpp中的main 函数分成核心部分进行阐述

int main(int argc, char** argv) {
    if (!strcmp(basename(argv[0]), "ueventd")) {
        return ueventd_main(argc, argv);
    }

    if (!strcmp(basename(argv[0]), "watchdogd")) {
        return watchdogd_main(argc, argv);
    }

    if (REBOOT_BOOTLOADER_ON_PANIC) {
        InstallRebootSignalHandlers();
    }

    add_environment("PATH", _PATH_DEFPATH);
    bool is_first_stage = (getenv("INIT_SECOND_STAGE") == nullptr);
    if (is_first_stage) {
        boot_clock::time_point start_time = boot_clock::now();

        // Clear the umask.
        umask(0);

        // Get the basic filesystem setup we need put together in the initramdisk
        // on / and then we'll let the rc file figure out the rest.
        mount("tmpfs", "/dev", "tmpfs", MS_NOSUID, "mode=0755");
        mkdir("/dev/pts", 0755);
        mkdir("/dev/socket", 0755);
        mount("devpts", "/dev/pts", "devpts", 0, NULL);
        #define MAKE_STR(x) __STRING(x)
        mount("proc", "/proc", "proc", 0, "hidepid=2,gid=" MAKE_STR(AID_READPROC));
        // Don't expose the raw commandline to unprivileged processes.
        chmod("/proc/cmdline", 0440);
        gid_t groups[] = { AID_READPROC };
        setgroups(arraysize(groups), groups);
        mount("sysfs", "/sys", "sysfs", 0, NULL);
        mount("selinuxfs", "/sys/fs/selinux", "selinuxfs", 0, NULL);
        mknod("/dev/kmsg", S_IFCHR | 0600, makedev(1, 11));
        mknod("/dev/random", S_IFCHR | 0666, makedev(1, 8));
        mknod("/dev/urandom", S_IFCHR | 0666, makedev(1, 9));

        // Now that tmpfs is mounted on /dev and we have /dev/kmsg, we can actually
        // talk to the outside world...
        InitKernelLogging(argv);

        LOG(INFO) << "init first stage started!";

        if (!DoFirstStageMount()) {
            LOG(ERROR) << "Failed to mount required partitions early ...";
            panic();
        }

        SetInitAvbVersionInRecovery();

        // Set up SELinux, loading the SELinux policy.
        selinux_initialize(true);

        // We're in the kernel domain, so re-exec init to transition to the init domain now
        // that the SELinux policy has been loaded.
        if (selinux_android_restorecon("/init", 0) == -1) {
            PLOG(ERROR) << "restorecon failed";
            security_failure();
        }

        setenv("INIT_SECOND_STAGE", "true", 1);

        static constexpr uint32_t kNanosecondsPerMillisecond = 1e6;
        uint64_t start_ms = start_time.time_since_epoch().count() / kNanosecondsPerMillisecond;
        setenv("INIT_STARTED_AT", std::to_string(start_ms).c_str(), 1);

        char* path = argv[0];
        char* args[] = { path, nullptr };
        execv(path, args);

        // execv() only returns if an error happened, in which case we
        // panic and never fall through this conditional.
        PLOG(ERROR) << "execv(\"" << path << "\") failed";
        security_failure();
    }

    // At this point we're in the second stage of init
   =============================================================================
    第一个部分,在init 进程中启动kernel log
    InitKernelLogging(argv);
    LOG(INFO) << "init second stage started!";

    // Set up a session keyring that all processes will have access to. It
    // will hold things like FBE encryption keys. No process should override
    // its session keyring.
    keyctl_get_keyring_ID(KEY_SPEC_SESSION_KEYRING, 1);

    // Indicate that booting is in progress to background fw loaders, etc.
    close(open("/dev/.booting", O_WRONLY | O_CREAT | O_CLOEXEC, 0000));

   =============================================================================
    第二个部分,property_init
    property_init();

    // If arguments are passed both on the command line and in DT,
    // properties set in DT always have priority over the command-line ones.
    process_kernel_dt();
    process_kernel_cmdline();

    // Propagate the kernel variables to internal variables
    // used by init as well as the current required properties.
    export_kernel_boot_props();

    // Make the time that init started available for bootstat to log.
    property_set("ro.boottime.init", getenv("INIT_STARTED_AT"));
    property_set("ro.boottime.init.selinux", getenv("INIT_SELINUX_TOOK"));

    // Set libavb version for Framework-only OTA match in Treble build.
    const char* avb_version = getenv("INIT_AVB_VERSION");
    if (avb_version) property_set("ro.boot.avb_version", avb_version);

    // Set memcg property based on kernel cmdline argument
    bool memcg_enabled = android::base::GetBoolProperty("ro.boot.memcg",false);
    if (memcg_enabled) {
       // root memory control cgroup
       mkdir("/dev/memcg", 0700);
       chown("/dev/memcg",AID_ROOT,AID_SYSTEM);
       mount("none", "/dev/memcg", "cgroup", 0, "memory");
       // app mem cgroups, used by activity manager, lmkd and zygote
       mkdir("/dev/memcg/apps/",0755);
       chown("/dev/memcg/apps/",AID_SYSTEM,AID_SYSTEM);
       mkdir("/dev/memcg/system",0550);
       chown("/dev/memcg/system",AID_SYSTEM,AID_SYSTEM);
    }

    // Clean up our environment.
    unsetenv("INIT_SECOND_STAGE");
    unsetenv("INIT_STARTED_AT");
    unsetenv("INIT_SELINUX_TOOK");
    unsetenv("INIT_AVB_VERSION");

    // Now set up SELinux for second stage.
    selinux_initialize(false);
    selinux_restore_context();

   =============================================================================
    第三个部分 创建epoll_fd, 利用此fd监控属性,signal_handle ,handle_keychord
    epoll_fd = epoll_create1(EPOLL_CLOEXEC);
    if (epoll_fd == -1) {
        PLOG(ERROR) << "epoll_create1 failed";
        exit(1);
    }
    signal_handler_init();

    property_load_boot_defaults();
    export_oem_lock_status();
    start_property_service();
    set_usb_controller();

    const BuiltinFunctionMap function_map;
    Action::set_function_map(&function_map);

   =============================================================================
    第四个部分  am,sm 建立,parser init.rc**
    ActionManager& am = ActionManager::GetInstance();
    ServiceManager& sm = ServiceManager::GetInstance();
    Parser& parser = Parser::GetInstance();

    parser.AddSectionParser("service", std::make_unique(&sm));
    parser.AddSectionParser("on", std::make_unique(&am));
    parser.AddSectionParser("import", std::make_unique(&parser));
    std::string bootscript = GetProperty("ro.boot.init_rc", "");
    if (bootscript.empty()) {
        parser.ParseConfig("/init.rc");
        parser.set_is_system_etc_init_loaded(
                parser.ParseConfig("/system/etc/init"));
        parser.set_is_vendor_etc_init_loaded(
                parser.ParseConfig("/vendor/etc/init"));
        parser.set_is_odm_etc_init_loaded(parser.ParseConfig("/odm/etc/init"));
    } else {
        parser.ParseConfig(bootscript);
        parser.set_is_system_etc_init_loaded(true);
        parser.set_is_vendor_etc_init_loaded(true);
        parser.set_is_odm_etc_init_loaded(true);
    }

    // Turning this on and letting the INFO logging be discarded adds 0.2s to
    // Nexus 9 boot time, so it's disabled by default.
    if (false) DumpState();

    am.QueueEventTrigger("early-init");

    // Queue an action that waits for coldboot done so we know ueventd has set up all of /dev...
    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(mix_hwrng_into_linux_rng_action, "mix_hwrng_into_linux_rng");
    am.QueueBuiltinAction(set_mmap_rnd_bits_action, "set_mmap_rnd_bits");
    am.QueueBuiltinAction(set_kptr_restrict_action, "set_kptr_restrict");
    am.QueueBuiltinAction(keychord_init_action, "keychord_init");
    am.QueueBuiltinAction(console_init_action, "console_init");

    // Trigger all the boot actions to get us started.
    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(mix_hwrng_into_linux_rng_action, "mix_hwrng_into_linux_rng");

    // Don't mount filesystems or start core system services in charger mode.
    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 ExecuteOneCommand  restart_processes epoll_fd
    while (true) {
        // By default, sleep until something happens.
        int epoll_timeout_ms = -1;

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

        if (!(waiting_for_prop || sm.IsWaitingForExec())) {
            am.ExecuteOneCommand();--->执行action
        }
        if (!(waiting_for_prop || sm.IsWaitingForExec())) {
            if (!shutting_down) restart_processes();------》 重启process ,根据sv flags 进行判断

            // If there's a process that needs restarting, wake up in time for that.
            if (process_needs_restart_at != 0) {
                epoll_timeout_ms = (process_needs_restart_at - time(nullptr)) * 1000;
                if (epoll_timeout_ms < 0) epoll_timeout_ms = 0;
            }

            // If there's more work to do, wake up again immediately.
            if (am.HasMoreCommands()) epoll_timeout_ms = 0;
        }

        epoll_event ev;
        int nr = TEMP_FAILURE_RETRY(epoll_wait(epoll_fd, &ev, 1, epoll_timeout_ms));-----》wait epoll_fd
        if (nr == -1) {
            PLOG(ERROR) << "epoll_wait failed";
        } else if (nr == 1) {
            ((void (*)()) ev.data.ptr)();
        }
    }

    return 0;
}

}  // namespace init
}  // namespace android

int main(int argc, char** argv) {
    android::init::main(argc, argv);
}

第一个部分,在init 进程中启动kernel log
在一个部分之前,调用了 selinux_initialize(true); 这里决定selinux 是否开启
selinux 是否开启

InitKernelLogging:

--->  InitKernelLogging(argv);
void InitKernelLogging(char* argv[]) {
    // Make stdin/stdout/stderr all point to /dev/null.---> 使用了 dev/null , 只是初始化动作
    int fd = open("/sys/fs/selinux/null", O_RDWR);
    if (fd == -1) {
        int saved_errno = errno;
        android::base::InitLogging(argv, &android::base::KernelLogger);
        errno = saved_errno;
        PLOG(FATAL) << "Couldn't open /sys/fs/selinux/null";
    }
    dup2(fd, 0);
    dup2(fd, 1);
    dup2(fd, 2);
    if (fd > 2) close(fd);

    android::base::InitLogging(argv, &android::base::KernelLogger);---》 传递参数KernelLogger
}

InitLogging 声明:默认初值

void InitLogging(char* argv[],
                 LogFunction&& logger = INIT_LOGGING_DEFAULT_LOGGER,
                 AbortFunction&& aborter = DefaultAborter);

system/core/base/logging.cpp

InitLogging(char* argv[], LogFunction&& logger, AbortFunction&& aborter) 
  ---> SetLogger(std::forward(logger));--->kernel log 
  ---> SetAborter(std::forward(aborter));---->aborter log
         ---> static auto& logger = *new LogFunction(LogdLogger());
         --->  static auto& aborter = *new AbortFunction(DefaultAborter);
}

第二个部分,property_init
bionic/libc/bionic/system_properties.cpp

property_init
       --->map_system_property_area,  --》创建区域,property 存储的地方

第三个部分 创建epoll_fd, 利用此fd监控属性,signal_handle ,handle_keychord
主要是对epoll_fd 的利用在什么地方:
system/core/init/keychords.cpp
system/core/init/property_service.cpp
system/core/init/signal_handler.cpp

epoll_fd = epoll_create1(EPOLL_CLOEXEC);
(1)--->signal_handler_init--->register_epoll_handler---> 注册epoll_fd
(2)--->keychord_init--->register_epoll_handler---> 注册epoll_fd
(3)--->start_property_service--->register_epoll_handler---> 注册epoll_fd
图片.png

signal_handler_init:创建了socketpair,init 进程的子进程死亡时候,发送SIGCHLD, init 父进程监听子进程死亡,启动SIGCHLD_handler 函数,SIGCHLD_handler write signal_write_fd, 这是signal_read_fd 就会可以读, 出发epoll 事件----------> 在 第五个部分 while 循环中,while就不再阻塞,进行一轮处理,然后再次epoll_wait epoll_fd
system/core/init/signal_handler.cpp

void signal_handler_init() {
    // Create a signalling mechanism for SIGCHLD.
    int s[2];
    if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0, s) == -1) {
        PLOG(ERROR) << "socketpair failed";
        exit(1);
    }
    signal_write_fd = s[0];
    signal_read_fd = s[1];
    
   // Write to signal_write_fd if we catch SIGCHLD.
    struct sigaction act;
    memset(&act, 0, sizeof(act));
    act.sa_handler = SIGCHLD_handler;
    act.sa_flags = SA_NOCLDSTOP;
    sigaction(SIGCHLD, &act, 0);

    ServiceManager::GetInstance().ReapAnyOutstandingChildren();
    register_epoll_handler(signal_read_fd, handle_signal);
}

system/core/init/signal_handler.cpp
SIGCHLD_handler:

static void SIGCHLD_handler(int) {
    if (TEMP_FAILURE_RETRY(write(signal_write_fd, "1", 1)) == -1) {
        PLOG(ERROR) << "write(signal_write_fd) failed";
    }
}

第四个部分 am,sm 建立,parser init.rc
system/core/init/init.cpp

......
ServiceManager& sm = ServiceManager::GetInstance();-------> static ServiceManager instance;
parser.AddSectionParser("service", std::make_unique(&sm));---->添加sm 到section_parsers_

parser.AddSectionParser("on", std::make_unique(&am));
parser.AddSectionParser("import", std::make_unique(&parser));

parser.ParseConfig("/init.rc");
......

system/core/init/init_parser.cpp

void Parser::AddSectionParser(const std::string& name,
                              std::unique_ptr parser) {
    section_parsers_[name] = std::move(parser); ---》根据键值对,添加【name, parser】
}

system/core/init/init_parser.cpp

ParseConfig---》ParseConfigFile---->ParseData
                    ---》ParseConfigDir
--------------------------------------------------------------------------------------------------------
ParseData:
void Parser::ParseData(const std::string& filename, const std::string& data) {
    ........
    for (;;) {
        switch (next_token(&state)) {
        case T_EOF:  ----》解析结束
            if (section_parser) {
                section_parser->EndSection();
            }
            return;
        case T_NEWLINE:-----》解析line
            state.line++;
            if (args.empty()) {
                break;
            }
            ............
            if (section_parsers_.count(args[0])) {
                if (section_parser) {
                    section_parser->EndSection();
                }
                section_parser = section_parsers_[args[0]].get();
                std::string ret_err;
                if (!section_parser->ParseSection(std::move(args), filename, state.line, &ret_err)) {------>根据 on、service或import解析section
                    LOG(ERROR) << filename << ": " << state.line << ": " << ret_err;
                    section_parser = nullptr;
                }
            } else if (section_parser) {
                std::string ret_err;
                if (!section_parser->ParseLineSection(std::move(args), state.line, &ret_err)) {   ----->解析section中的line,其中option(例如oneshot,class等),并将这些属性添加到Service对象中
                    LOG(ERROR) << filename << ": " << state.line << ": " << ret_err;
                }
            }
            args.clear();
            break;
        case T_TEXT:
            args.emplace_back(state.text);
            break;
        }
    }
}

system/core/init/service.cpp

-------------------------------------------------------------------------------------------------------------
bool ServiceParser::ParseSection(std::vector&& args, const std::string& filename,
                                 int line, std::string* err) {
    if (args.size() < 3) {
        *err = "services must have a name and a program";
        return false;
    }

    const std::string& name = args[1];
    if (!IsValidName(name)) {
        *err = StringPrintf("invalid service name '%s'", name.c_str());
        return false;
    }

    Service* old_service = service_manager_->FindServiceByName(name);
    if (old_service) {
        *err = "ignored duplicate definition of service '" + name + "'";
        return false;
    }

    std::vector str_args(args.begin() + 2, args.end());
    service_ = std::make_unique(name, str_args);------>创建了service_
    return true;
}
-------------------------------------------------------------------------------------------------------------
void ServiceParser::EndSection() {
    if (service_) {
        service_manager_->AddService(std::move(service_));-----> 添加service_ 到serivce_manager
    }
}
<--------------------AddService--------------------->
void ServiceManager::AddService(std::unique_ptr service) {
    services_.emplace_back(std::move(service));--> 添加到service list  services_中
}
-------------------------------------------------------------------------------------------------------------
bool ServiceParser::ParseLineSection(std::vector&& args, int line, std::string* err) {
    return service_ ? service_->ParseLine(std::move(args), err) : false;----->解析service options
}

-------------------------------------------ParseLine-----------------------------------------------------
bool Service::ParseLine(const std::vector& args, std::string* err) {
    static const OptionParserMap parser_map;
    auto parser = parser_map.FindFunction(args, err);

    if (!parser) {
        return false;
    }
    return (this->*parser)(args, err);  ----->执行相应属性parser_map中的函数,添加对应的属性到Service对象中
}

system/core/init/service.cpp
OptionParserMap :

    static const Map option_parsers = {
        {"class",       {1,     kMax, &Service::ParseClass}},
        {"critical",    {0,     0,    &Service::ParseCritical}},
        {"disabled",    {0,     0,    &Service::ParseDisabled}},
        {"group",       {1,     NR_SVC_SUPP_GIDS + 1, &Service::ParseGroup}},
        {"keycodes",    {1,     kMax, &Service::ParseKeycodes}},
        {"oneshot",     {0,     0,    &Service::ParseOneshot}},
      ......
    };

system/core/init/service.cpp
ParseDisabled:

bool Service::ParseDisabled(const std::vector& args, std::string* err) {
    flags_ |= SVC_DISABLED; ---->set svc flags---->service 决定service 启动方式, 是在 xxx.rc 中option 定义
    flags_ |= SVC_RC_DISABLED;
    return true;
}
图片.png

上面的分析可以看出ServiceParser的ParseLineSection是直接执行option对应函数,读者如果分析ActionParser是将对应函数保存到commands_数组中,当Action触发时,才会依次执行command函数。

第五个部分 while ExecuteOneCommand restart_processes epoll_fd

讲解第五部分之前,先看看QueueEventTrigger, QueueBuiltinAction

system/core/init/init.cpp

void ActionManager::QueueEventTrigger(const std::string& trigger) {
    event_queue_.emplace(trigger);-------->on action
}

void ActionManager::QueueBuiltinAction(BuiltinFunction func, const std::string& name) {
    auto action = std::make_unique(true, "", 0);
    std::vector name_vector{name};

    if (!action->InitSingleTrigger(name)) {
        return;
    }

    action->AddCommand(func, name_vector, 0);----》 添加action command
    event_queue_.emplace(action.get());
    actions_.emplace_back(std::move(action));
}

android init 最后进入了 epoll_wait等待

while (true) {
          am.ExecuteOneCommand();----》5.1 执行命令
          restart_processes();----》5.2 restart process 
          epoll_wait(epoll_fd, &ev, 1, epoll_timeout_ms) -->待定fd 出发,监控 property , SIGCHLD,keychord
}

5.1 执行命令& service
system/core/init/action.cpp

void ActionManager::ExecuteOneCommand() {
    // Loop through the event queue until we have an action to execute
    while (current_executing_actions_.empty() && !event_queue_.empty()) {
        for (const auto& action : actions_) {--->轮询actions_
            if (std::visit([&action](const auto& event) { return action->CheckEvent(event); },
                           event_queue_.front())) {
                current_executing_actions_.emplace(action.get());  -->添加到current_executing_actions_ 中
            }
        }
        event_queue_.pop();
    }

    if (current_executing_actions_.empty()) {
        return;
    }
    auto action = current_executing_actions_.front();
    if (current_command_ == 0) {
        std::string trigger_name = action->BuildTriggersString();
        LOG(INFO) << "processing action (" << trigger_name << ") from (" << action->filename()
                  << ":" << action->line() << ")";
    }

    action->ExecuteOneCommand(current_command_);----> 执行

    // If this was the last command in the current action, then remove
    // the action from the executing list.
    // If this action was oneshot, then also remove it from actions_.

    阅读上面的注释:就可以知道侦测命令的多少,是否最后一个
    ++current_command_;
    if (current_command_ == action->NumCommands()) {
        current_executing_actions_.pop();
        current_command_ = 0;
        if (action->oneshot()) {
            auto eraser = [&action] (std::unique_ptr& a) {
                return a.get() == action;
            };
            actions_.erase(std::remove_if(actions_.begin(), actions_.end(), eraser));
        }
    }
}

ExecuteOneCommand:

void Action::ExecuteOneCommand(std::size_t command) const {
    // We need a copy here since some Command execution may result in
    // changing commands_ vector by importing .rc files through parser
    Command cmd = commands_[command];
    ExecuteCommand(cmd);
}
----------------------------------------------------------------------------------------------
void Action::ExecuteCommand(const Command& command) const {
    android::base::Timer t;
    int result = command.InvokeFunc();---》 执行

    auto duration = t.duration();
    // Any action longer than 50ms will be warned to user as slow operation
    if (duration > 50ms || android::base::GetMinimumLogSeverity() <= android::base::DEBUG) {
        std::string trigger_name = BuildTriggersString();
        std::string cmd_str = command.BuildCommandString();

        LOG(INFO) << "Command '" << cmd_str << "' action=" << trigger_name << " (" << filename_
                  << ":" << command.line() << ") returned " << result << " took "
                  << duration.count() << "ms.";
    }
}

5.2 restart process
system/core/init/init.cpp

static void restart_processes()
{
    process_needs_restart_at = 0;
    ServiceManager::GetInstance().ForEachServiceWithFlags(SVC_RESTARTING, [](Service* s) {--->根据SVC flags 决定是否重启
        s->RestartIfNeeded(&process_needs_restart_at);
    });
}

system/core/init/service.cpp

void Service::RestartIfNeeded(time_t* process_needs_restart_at) {
    boot_clock::time_point now = boot_clock::now();
    boot_clock::time_point next_start = time_started_ + 5s;
    if (now > next_start) {
        flags_ &= (~SVC_RESTARTING);
        Start();----->重启service
        return;
    }

   就是一些时间的设定,启动时间控制
    time_t next_start_time_t = time(nullptr) +
        time_t(std::chrono::duration_cast(next_start - now).count());
    if (next_start_time_t < *process_needs_restart_at || *process_needs_restart_at == 0) {
        *process_needs_restart_at = next_start_time_t;
    }
}

service 启动调用逻辑:

(init.cpp)sm.IsWaitingForExec()---->
    (init.cpp)restart_processes();---->
        ServiceManager::ForEachServiceWithFlags---> (service.cpp) 
              Service::RestartIfNeeded---->
                 Service::Start()--->启动service

有上面的可以知道,init main 主要的工作:log ,文件挂载,异常处理,解析rc 文件,启动service,启动property, 最后进入了epoll fd 等待

REF:
https://android.googlesource.com/platform/system/core/+/master/init/README.md

你可能感兴趣的:(android-init)