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;
}
|