Android 13 init进程(二)

本文涉及的产品
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
云解析 DNS,旗舰版 1个月
全局流量管理 GTM,标准版 1个月
简介: 学习笔记

init进程启动第二阶段

主要负责:

  • 创建进程会话密钥,并初始化属性系统
  • 执行SELinux第二阶段,并恢复一些文件安全上下文
  • 新建epoll,并初始化子进程终止信号处理函数
  • 设置其他系统属性,并开启属性服务
  • 解析init.rc等文件,建立rc文件的action、service,启动其他进程


image.png

/android/system/core/init/init.cpp

intSecondStageMain(intargc, char** argv) {

    #ifdef JOURNEY_FEATURE_ROOT_MODE

    initJourneyRootMode();

    #endif

    /*

*init crash时重启引导加载程序

*这个函数主要作用将各种信号量,如SIGABRT,SIGBUS等的行为设置为SA_RESTART,一旦监听到这些信号即执行重启系统

*/

    if(REBOOT_BOOTLOADER_ON_PANIC) {

        InstallRebootSignalHandlers();

    }

 

    boot_clock::time_point start_time = boot_clock::now();

 

    trigger_shutdown = [](conststd::string& command) { shutdown_state.TriggerShutdown(command); };

    //把标准输入、标准输出和标准错误重定向到空设备文件“/dev/null"

    SetStdioToDevNull(argv);

    #ifdef MTK_LOG

    #ifndef MTK_LOG_DISABLERATELIMIT

    {

        std::string cmdline;

        android::base::ReadFileToString("/proc/cmdline", &cmdline);

 

        if(cmdline.find("init.mtklogdrl=1") != std::string::npos)

            SetMTKLOGDISABLERATELIMIT();

 

        constchar* force_debuggable_env = getenv("INIT_FORCE_DEBUGGABLE");

        if(force_debuggable_env && AvbHandle::IsDeviceUnlocked()) {

            SetMTKLOGDISABLERATELIMIT();

        }

    }

    #else

    SetMTKLOGDISABLERATELIMIT();

    #endif // MTK_LOG_DISABLERATELIMIT

 

    if(GetMTKLOGDISABLERATELIMIT())

        InitKernelLogging_split(argv);

    else

        InitKernelLogging(argv);

    #else

    //在/dev目录下挂载好tmpfs以及kmsg

    //这样就可以初始化/kernel log系统,供用户打印log

    InitKernelLogging(argv);

    #endif

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

 

    // Update $PATH in the case the second stage init is newer than first stage init, where it is

    // first set.

    if(setenv("PATH", _PATH_DEFPATH, 1) != 0) {

        PLOG(FATAL) << "Could not set $PATH to '"<< _PATH_DEFPATH << "' in second stage";

    }

 

    // Init should not crash because of a dependence on any other process, therefore we ignore

    // SIGPIPE and handle EPIPE at the call site directly.  Note that setting a signal to SIG_IGN

    // is inherited across exec, but custom signal handlers are not.  Since we do not want to

    // ignore SIGPIPE for child processes, we set a no-op function for the signal handler instead.

    {

        structsigaction action = {.sa_flags = SA_RESTART};

        action.sa_handler = [](int) {};

        sigaction(SIGPIPE, &action, nullptr);

    }

 

    // Set init and its forked children's oom_adj.

    if(auto result =

        WriteFile("/proc/1/oom_score_adj", StringPrintf("%d", DEFAULT_OOM_SCORE_ADJUST));

        !result.ok()) {

        LOG(ERROR) << "Unable to write "<< DEFAULT_OOM_SCORE_ADJUST

            << " to /proc/1/oom_score_adj: "<< result.error();

    }

 

    // 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.

    //01.创建进程会话密钥并初始化属性系统

    keyctl_get_keyring_ID(KEY_SPEC_SESSION_KEYRING, 1);

 

    // Indicate that booting is in progress to background fw loaders, etc.

    //创建/dev/.booting文件,就是个标记,表示booting进行中

    close(open("/dev/.booting", O_WRONLY | O_CREAT | O_CLOEXEC, 0000));

 

    // See if need to load debug props to allow adb root, when the device is unlocked.

constchar* force_debuggable_env = getenv("INIT_FORCE_DEBUGGABLE");

boolload_debug_prop = false;

if(force_debuggable_env && AvbHandle::IsDeviceUnlocked()) {

load_debug_prop = "true"s == force_debuggable_env;

}

unsetenv("INIT_FORCE_DEBUGGABLE");

 

// Umount the debug ramdisk so property service doesn't read .prop files from there, when it

// is not meant to.

if(!load_debug_prop) {

UmountDebugRamdisk();

}

 

//初始化属性系统,并从指定文件读取属性

PropertyInit();

 

// Umount second stage resources after property service has read the .prop files.

UmountSecondStageRes();

 

// Umount the debug ramdisk after property service has read the .prop files when it means to.

if(load_debug_prop) {

UmountDebugRamdisk();

}

 

// Mount extra filesystems required during second stage init

MountExtraFilesystems();

 

// Now set up SELinux for second stage.

#ifdef MTK_LOG

if(GetMTKLOGDISABLERATELIMIT())

SelinuxSetupKernelLogging_split();

else

SelinuxSetupKernelLogging();

#else

SelinuxSetupKernelLogging();

#endif

SelabelInitialize();

/*

02.进行SELinux第二阶段并恢复一些文件安全上下文

恢复相关文件的安全上下文,因为这些文件是在SELinux安全机制初始化前创建的

所以需要重新恢复上下文

*/

SelinuxRestoreContext();

 

/*

03.新建epoll并初始化子进程终止信号处理函数

创建epoll实例,并返回epoll的文件描述

*/

Epoll epoll;

if(auto result = epoll.Open(); !result.ok()) {

PLOG(FATAL) << result.error();

}

 

#ifdef G1122717

// Watch properties with specific meanings to init.

LOG(INFO) << "Apply watching properties with specific meanings to init.";

ActionManager::GetInstance().StartWatchingProperty("sys.powerctl");

ActionManager::GetInstance().StartWatchingProperty("ro.persistent_properties.ready");

ActionManager::GetInstance().StartWatchingProperty(kColdBootDoneProp);

#endif

/*

主要是创建handler处理子进程终止信号,注册一个signal到epoll进行监听

进行子继承处理

*/

InstallSignalFdHandler(&epoll);

InstallInitNotifier(&epoll);

 

//04.设置其他系统属性并开启系统属性服务

StartPropertyService(&property_fd);

 

#if defined(MTK_LOG) && defined(MTK_COMMAND_WDOG)

ActionManager::GetInstance().StartCommandWDOG();

#endif

 

// Make the time that init stages started available for bootstat to log.

RecordStageBoottimes(start_time);

 

// Set libavb version for Framework-only OTA match in Treble build.

if(constchar* avb_version = getenv("INIT_AVB_VERSION"); avb_version != nullptr) {

SetProperty("ro.boot.avb_version", avb_version);

}

unsetenv("INIT_AVB_VERSION");

 

fs_mgr_vendor_overlay_mount_all();

export_oem_lock_status();

MountHandler mount_handler(&epoll);

SetUsbController();

#ifdef JOURNEY_FEATURE_SECURE

CheckJourneySecureMode();

#endif

 

constBuiltinFunctionMap& function_map = GetBuiltinFunctionMap();

Action::set_function_map(&function_map);

 

if(!SetupMountNamespaces()) {

PLOG(FATAL) << "SetupMountNamespaces failed";

}

 

//初始化文件上下文

InitializeSubcontext();

 

ActionManager& am = ActionManager::GetInstance();

ServiceList& sm = ServiceList::GetInstance();

/*

05.解析init.rc等文件,建立rc文件的action、service,启动其他进程

*/

LoadBootScripts(am, sm);

 

// 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();

 

// Make the GSI status available before scripts start running.

//当GSI脚本running时,确保GSI状态可用

auto is_running = android::gsi::IsGsiRunning() ? "1""0";

SetProperty(gsi::kGsiBootedProp, is_running);

auto is_installed = android::gsi::IsGsiInstalled() ? "1""0";

SetProperty(gsi::kGsiInstalledProp, is_installed);

 

am.QueueBuiltinAction(SetupCgroupsAction, "SetupCgroups");

am.QueueBuiltinAction(SetKptrRestrictAction, "SetKptrRestrict");

am.QueueBuiltinAction(TestPerfEventSelinuxAction, "TestPerfEventSelinux");

//执行rc文件中触发器为 on early-init的语句

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(SetMmapRndBitsAction, "SetMmapRndBits");

//设备组合键的初始化操作

Keychords keychords;

am.QueueBuiltinAction(

[&epoll, &keychords](constBuiltinArguments& args) -> Result<void> {

for(constauto& svc : ServiceList::GetInstance()) {

keychords.Register(svc->keycodes());

}

keychords.Start(&epoll, HandleKeychord);

return{};

},

"KeychordInit");

 

// Trigger all the boot actions to get us started.

//执行rc文件中触发器为on init的语句

am.QueueEventTrigger("init");

 

// Don't mount filesystems or start core system services in charger mode.

/*

当设备处于充电模式时,不需要mount文件系统或者启动系统服务

充电模式下,将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");

 

// Restore prio before main loop

setpriority(PRIO_PROCESS, 0, 0);

while(true) {

// By default, sleep until something happens.

auto epoll_timeout = std::optional<std::chrono::milliseconds>{};

 

auto shutdown_command = shutdown_state.CheckShutdown();

if(shutdown_command) {

LOG(INFO) << "Got shutdown_command '"<< *shutdown_command

<< "' Calling HandlePowerctlMessage()";

HandlePowerctlMessage(*shutdown_command);

shutdown_state.set_do_shutdown(false);

}

 

//依次执行每个action中携带command对应的执行函数

if(!(prop_waiter_state.MightBeWaiting() || Service::is_exec_service_running())) {

am.ExecuteOneCommand();

}

if(!IsShuttingDown()) {

auto next_process_action_time = HandleProcessActions();

 

// If there's a process that needs restarting, wake up in time for that.

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;

}

 

#ifdef MTK_LOG

intlog_ms = _LogReap();//PropSetLogReap();

if(log_ms > -1 && (!epoll_timeout || epoll_timeout->count() > log_ms))

epoll_timeout = std::chrono::milliseconds(log_ms);

 

if(GetMTKLOGDISABLERATELIMIT()) {

if(!Getwhilepiggybacketed(1) && Getwhileepduration(1) > 1999)

LOG(INFO) << "Lastest epoll wait tooks "<< Getwhileepduration(1) << "ms";

}

 

android::base::Timer t;

 

auto pending_functions = epoll.Wait(epoll_timeout);

 

if(GetMTKLOGDISABLERATELIMIT()) {

uint64_t duration = t.duration().count();

uint64_t nowms = std::chrono::duration_cast<std::chrono::milliseconds>(boot_clock::now().time_since_epoch()).count();

Setwhiletime(1, duration, nowms);

}

#else

auto pending_functions = epoll.Wait(epoll_timeout);

#endif

if(!pending_functions.ok()) {

LOG(ERROR) << pending_functions.error();

elseif(!pending_functions->empty()) {

// We always reap children before responding to the other pending functions. This is to

// prevent a race where other daemons see that a service has exited and ask init to

// start it again via ctl.start before init has reaped it.

ReapAnyOutstandingChildren();

for(constauto& function : *pending_functions) {

(*function)();

}

}

if(!IsShuttingDown()) {

HandleControlMessages();

SetUsbController();

}

}

 

return0;

}

信号处理

init是一个守护进程,为了防止init的子进程成为僵尸进程(zombie process),需要init在子进程在结束时获取子进程的结束码,通过结束码将程序表中的子进程移除,防止成为僵尸进程的子进程占用程序表的空间(程序表的空间达到上限时,系统就不能再启动新的进程了,会引起严重的系统问题)。

信号处理主要工作:

  • 初始化信号signal句柄
  • 循环处理子进程
  • 注册epoll句柄
  • 处理子进程终止

注: EPOLL类似于POLL,是Linux中用来做事件触发的,跟EventBus功能差不多。linux很长的时间都在使用select来做事件触发,它是通过轮询来处理的,轮询的fd数目越多,自然耗时越多,对于大量的描述符处理,EPOLL更有优势

InstallSignalFdHandler

在linux当中,父进程是通过捕捉SIGCHLD信号来得知子进程运行结束的情况,SIGCHLD信号会在子进程终止的时候发出,了解这些背景后,我们来看看init进程如何处理这个信号。

  • 首先,新建一个sigaction结构体,sa_handler是信号处理函数,指向内核指定的函数指针SIG_DFL和Android 9.0及之前的版本不同,这里不再通过socket的读写句柄进行接收信号,改成了内核的信号处理函数SIG_DFL。
  • 然后,sigaction(SIGCHLD, &act, nullptr) 这个是建立信号绑定关系,也就是说当监听到SIGCHLD信号时,由act这个sigaction结构体处理
  • 最后,RegisterHandler 的作用就是signal_read_fd(之前的s[1])收到信号,触发handle_signal

终上所述,InstallSignalFdHandler函数的作用就是,接收到SIGCHLD信号时触发HandleSignalFd进行信号处理

信号处理示意图:

image.png

/android/system/core/init/init.cpp

staticvoidInstallSignalFdHandler(Epoll* epoll) {

    //SA_NOCLDSTOP使init进程只有在其进程终止时才会受到SIGCHLD信号

    conststructsigaction act { .sa_handler = SIG_DFL, .sa_flags = SA_NOCLDSTOP };

    sigaction(SIGCHLD, &act, nullptr);

 

    sigset_t mask;

    sigemptyset(&mask);

    sigaddset(&mask, SIGCHLD);

 

    if(!IsRebootCapable()) {

        //如果init不具备CAP_SYS_BOOT的能力,则它此时正值容器中运行

        //在这种场景下,接收SIGTERM将会导致系统关闭

        sigaddset(&mask, SIGTERM);

    }

 

    if(sigprocmask(SIG_BLOCK, &mask, nullptr) == -1) {

        PLOG(FATAL) << "failed to block signals";

    }

 

    //注册处理程序以解除对子进程中的信号的阻止

    constintresult = pthread_atfork(nullptr, nullptr, &UnblockSignals);

    if(result != 0) {

        LOG(FATAL) << "Failed to register a fork handler: "<< strerror(result);

    }

 

    //创建信号句柄

    signal_fd = signalfd(-1, &mask, SFD_CLOEXEC);

    if(signal_fd == -1) {

        PLOG(FATAL) << "failed to create signalfd";

    }

 

    //信号注册,当signal_fd收到信号时,触发HandlerSignalFd

    if(auto result = epoll->RegisterHandler(signal_fd, HandleSignalFd); !result.ok()) {

        LOG(FATAL) << result.error();

    }

}

RegisterHandler

说明:信号注册,把fd句柄加入到epoll_fd_的监听队列中

/android/system/core/init/epoll.cpp

Result<void> Epoll::RegisterHandler(intfd, Handler handler, uint32_t events) {

    if(!events) {

        returnError() << "Must specify events";

    }

    auto sp = std::make_shared<decltype(handler)>(std::move(handler));

    auto [it, inserted] = epoll_handlers_.emplace(fd, std::move(sp));

    if(!inserted) {

        returnError() << "Cannot specify two epoll handlers for a given FD";

    }

    epoll_event ev;

    ev.events = events;

    // std::map's iterators do not get invalidated until erased, so we use the

    // pointer to the std::function in the map directly for epoll_ctl.

    ev.data.ptr = reinterpret_cast<void*>(&it->second);

    //将fd的可读事件加入到epoll_fd_的监听队列中

    if(epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, fd, &ev) == -1) {

        Result<void> result = ErrnoError() << "epoll_ctl failed to add fd";

        epoll_handlers_.erase(fd);

        returnresult;

    }

    return{};

}

HandlerSignalFd

说明:监控SIGCHLD信号,调用ReapAnyOutstadingChildren来终止出现问题的子进程

/android/system/core/init/init.cpp

staticvoidHandleSignalFd() {

    signalfd_siginfo siginfo;

    ssize_t bytes_read = TEMP_FAILURE_RETRY(read(signal_fd, &siginfo, sizeof(siginfo)));

    if(bytes_read != sizeof(siginfo)) {

        PLOG(ERROR) << "Failed to read siginfo from signal_fd";

        return;

    }

    //监控SIGCHLD信号

    switch(siginfo.ssi_signo) {

        caseSIGCHLD:

            ReapAnyOutstandingChildren();

            break;

        caseSIGTERM:

            HandleSigtermSignal(siginfo);

            break;

        default:

            PLOG(ERROR) << "signal_fd: received unexpected signal "<< siginfo.ssi_signo;

            break;

    }

}

ReapAnyOutstandingChildren

/android/system/core/init/sigchld_handler.cpp

voidReapAnyOutstandingChildren() {

    while(ReapOneProcess() != 0) {

    }

}

最终会调用到ReapOneProcess()方法

ReapOneProcess

说明:ReapOneProcess是最终的处理函数,这个函数先调用waitpid找出挂掉进程的pid,然后根据pid找到对应Service,最后调用Service的Reap方法清除资源,根据进程对应的类型,决定是否重启机器或重启进程

/android/system/core/init/sigchld_handler.cpp

staticpid_t ReapOneProcess() {

    siginfo_t siginfo = {};

    //用waitpid函数获取状态发生变化的子进程pid

    //waitpid的标记为WNOHANG,即非阻塞,返回为正值就说明有进程挂掉了

    if(TEMP_FAILURE_RETRY(waitid(P_ALL, 0, &siginfo, WEXITED | WNOHANG | WNOWAIT)) != 0) {

        PLOG(ERROR) << "waitid failed";

        return0;

    }

 

    auto pid = siginfo.si_pid;

    if(pid == 0) return0;

 

    //当我们知道当前有一个僵尸pid,我们使用scopeguard来清除该pid

    auto reaper = make_scope_guard([pid] { TEMP_FAILURE_RETRY(waitpid(pid, nullptr, WNOHANG)); });

 

    std::string name;

    std::string wait_string;

    Service* service = nullptr;

 

    if(SubcontextChildReap(pid)) {

        name = "Subcontext";

    else{

        //通过该pid找到对应的service

        service = ServiceList::GetInstance().FindService(pid, &Service::pid);

 

        if(service) {

            name = StringPrintf("Service '%s' (pid %d)", service->name().c_str(), pid);

            if(service->flags() & SVC_EXEC) {

                auto exec_duration = boot_clock::now() - service->time_started();

                auto exec_duration_ms =

                std::chrono::duration_cast<std::chrono::milliseconds>(exec_duration).count();

                wait_string = StringPrintf(" waiting took %f seconds", exec_duration_ms / 1000.0f);

            elseif(service->flags() & SVC_ONESHOT) {

                auto exec_duration = boot_clock::now() - service->time_started();

                auto exec_duration_ms =

                std::chrono::duration_cast<std::chrono::milliseconds>(exec_duration)

                .count();

                wait_string = StringPrintf(" oneshot service took %f seconds in background",

                    exec_duration_ms / 1000.0f);

            }

        else{

            name = StringPrintf("Untracked pid %d", pid);

        }

    }

 

    if(siginfo.si_code == CLD_EXITED) {

        LOG(INFO) << name << " exited with status "<< siginfo.si_status << wait_string;

    else{

        LOG(INFO) << name << " received signal "<< siginfo.si_status << wait_string;

    }

    //没有找到service,说明已经结束了,退出

    if(!service) returnpid;

    //清除子进程相关的资源

    service->Reap(siginfo);

 

    if(service->flags() & SVC_TEMPORARY) {

        ServiceList::GetInstance().RemoveService(*service);//移除该service

    }

 

    returnpid;

}

解析init.rc

当属性服务建立完成后,init的自身功能基本就告一段落,接下来需要来启动其他的进程。但是init进程如何其他其他进程呢?其他进程都是一个二进制文件,我们可以直接通过exec的命令方式来启动,例如 ./system/bin/init second_stage,来启动init进程的第二阶段。但是Android系统有那么多的Native进程,如果都通过传exec在代码中一个个的来执行进程,那无疑是一个灾难性的设计。

init.rc是一个配置文件,内部由Android初始化语言编写(Android Init Language)编写的脚本。类似通过读取配置文件的方式,来启动不同的进程。

LoadBootScripts

说明:如果没有特殊配置ro.boot.init_rc,则解析./init.rc

把/system/etc/init、/system_ext/etc/init、/odm/etc/init、/product/etc/init这几个路径加入init.rc之后解析的路径,在init.rc解析完成后,解析这些目录里面rc文件

注意:init.rc位于/system/core/rootdir下

/android/system/core/init/init.cpp

staticvoidLoadBootScripts(ActionManager& action_manager, ServiceList& service_list) {

    Parser parser = CreateParser(action_manager, service_list);

 

    std::string bootscript = GetProperty("ro.boot.init_rc""");

    if(bootscript.empty()) {

        parser.ParseConfig("/system/etc/init/hw/init.rc");

        if(!parser.ParseConfig("/system/etc/init")) {

            late_import_paths.emplace_back("/system/etc/init");

        }

        // late_import is available only in Q and earlier release. As we don't

        // have system_ext in those versions, skip late_import for system_ext.

        parser.ParseConfig("/system_ext/etc/init");

        if(!parser.ParseConfig("/vendor/etc/init")) {

            late_import_paths.emplace_back("/vendor/etc/init");

        }

        if(!parser.ParseConfig("/odm/etc/init")) {

            late_import_paths.emplace_back("/odm/etc/init");

        }

        if(!parser.ParseConfig("/product/etc/init")) {

            late_import_paths.emplace_back("/product/etc/init");

        }

    else{

        parser.ParseConfig(bootscript);

    }

}

Android7.0后,init.rc进行了拆分,每个服务都有自己的rc文件,他们基本上都被加载到/system/etc/init,/vendor/etc/init, /odm/etc/init等目录,等init.rc解析完成后,会来解析这些目录中的rc文件,用来执行相关的动作。

CreateParser

说明:创建Parser解析对象,例如service、on、import对象

Parser CreateParser(ActionManager& action_manager, ServiceList& service_list) {

    Parser parser;

 

    parser.AddSectionParser("service", std::make_unique<ServiceParser>(

                            &service_list, GetSubcontext(), std::nullopt));

    parser.AddSectionParser("on", std::make_unique<ActionParser>(&action_manager, GetSubcontext()));

    parser.AddSectionParser("import", std::make_unique<ImportParser>(&parser));

 

    returnparser;

}

执行Action动作

按顺序把相关Action加入触发器队列,按顺序为 early-init -> init -> late-init. 然后在循环中,执行所有触发器队列中Action带Command的执行函数。

am.QueueEventTrigger("early-init");

am.QueueEventTrigger("init");

am.QueueEventTrigger("late-init");

...

while(true) {

if(!(waiting_for_prop || Service::is_exec_service_running())) {

            am.ExecuteOneCommand();

        }

}

Zygote启动

从Android 5.0的版本开始,Android支持64位的编译,因此zygote本身也支持32位和64位。通过属性ro.zygote来控制不同版本的zygote进程启动。

在init.rc的import段我们看到如下代码:

/android/system/core/rootdir/init.rc

import /system/etc/init/hw/init.${ro.zygote}.rc // 可以看出init.rc不再直接引入一个固定的文件,而是根据属性ro.zygote的内容来引入不同的文件

init.rc位于/system/core/rootdir下。在这个路径下还包括四个关于zygote的rc文件。

分别是init.zygote32.rc,init.zygote32_64.rc,init.zygote64.rc,init.zygote64_32.rc,由硬件决定调用哪个文件。

这里拿64位处理器为例,init.zygote64.rc的代码如下所示:

/android/system/core/rootdir/init.zygote64.rc

service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server

classmain

    priority -20

    user root

    group root readproc reserved_disk

    socket zygote stream 660 root system

    socket usap_pool_primary stream 660 root system

    onrestart exec_background - systemsystem-- /system/bin/vdc volume abort_fuse

    onrestart write /sys/power/state on

    onrestart restart audioserver

    onrestart restart cameraserver

    onrestart restart media

    onrestart restart netd

    onrestart restart wificond

    writepid /dev/cpuset/foreground/tasks

    critical window=${zygote.critical_window.minute:-off} target=zygote-fatal

service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server 解析:

service zygote :init.zygote64.rc 中定义了一个zygote服务。 init进程就是通过这个service名称来创建zygote进程

/system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server解析:

zygote这个服务,通过执行进行/system/bin/app_process64 并传入4个参数进行运行:

  • 参数1:-Xzygote 该参数将作为虚拟机启动时所需的参数
  • 参数2:/system/bin 代表虚拟机程序所在目录
  • 参数3:--zygote 指明以ZygoteInit.java类中的main函数作为虚拟机执行入口
  • 参数4:--start-system-server 告诉Zygote进程启动systemServer进程

init总结

init进程主要分为两个阶段,

第一个阶段主要完成了:

  • 创建文件系统目录,并挂载了相关文件系统
  • 初始化了日志输出系统
  • 加载了SELinux(访问控制安全模块)安全策略
  • 进入第二阶段

第二阶段主要完成了

  • 初始化了属性系统
  • 执行了SELinux第二阶段,并恢复了一些文件的安全上下文
  • 新建了epoll,并初始化了子进程终止信号处理函数
  • 设置了系统其他属性,并开启了属性系统
  • 解析init.rc来启动其他进程
相关文章
|
6天前
|
Java Android开发 数据安全/隐私保护
Android中多进程通信有几种方式?需要注意哪些问题?
本文介绍了Android中的多进程通信(IPC),探讨了IPC的重要性及其实现方式,如Intent、Binder、AIDL等,并通过一个使用Binder机制的示例详细说明了其实现过程。
51 4
|
22天前
|
API Android开发
Android P 性能优化:创建APP进程白名单,杀死白名单之外的进程
本文介绍了在Android P系统中通过创建应用进程白名单并杀死白名单之外的进程来优化性能的方法,包括设置权限、获取运行中的APP列表、配置白名单以及在应用启动时杀死非白名单进程的代码实现。
41 1
|
22天前
|
Android开发
我的Android进阶修炼:安卓启动流程之init(1)
本文深入分析了Android系统中的init进程,包括其源码结构、主要功能以及启动流程的详细注解,旨在帮助读者理解init作为用户空间的1号进程在Android启动过程中的关键作用。
24 1
|
1月前
|
Android开发 开发者 Kotlin
Android 多进程情况下判断应用是否处于前台或者后台
本文介绍在多进程环境下判断Android应用前后台状态的方法。通过`ActivityManager`和服务信息`RunningAppProcessInfo`可有效检测应用状态,优化资源使用。提供Kotlin代码示例,帮助开发者轻松集成。
162 8
|
3月前
|
大数据 Linux Android开发
Android ParcelFileDescriptor实现进程间通信
Android ParcelFileDescriptor实现进程间通信
56 0
|
4月前
|
XML 前端开发 Android开发
Android架构设计——MVC(1),Android多进程从头讲到尾
Android架构设计——MVC(1),Android多进程从头讲到尾
|
4月前
|
安全 Linux API
Android进程与线程
Android进程与线程
41 0
|
12月前
|
Java Linux Android开发
理解Android进程创建流程
理解Android进程创建流程
92 0
|
Shell Android开发
Android init language与init.rc初始化脚本
Android init language与init.rc初始化脚本
69 0
|
Unix Linux Android开发
Android C++系列:Linux进程间通信(二)
mmap可以把磁盘文件的一部分直接映射到内存,这样文件中的位置直接就有对应的内存 地址,对文件的读写可以直接用指针来做而不需要read/write函数。
98 0

相关实验场景

更多