Android中的init进程是安卓系统用户空间启动的第一个进程。
相关源码:
system\core\reboot\reboot.c
system\core\init\init.cpp
system\core\init\reboot.cpp
inti进程源码路径为:
system/core/init/
reboot启动路程
reboot是一个二进制可执行文件,其源码路径为:
system\core\reboot
该目录只有两个文件,一个编译文件,一个c文件:
Android.bp
reboot.c
在system\core\reboot目录下编译,生成reboot可执行文件,生成目录在system/bin中
当我们在执行reboot命令时,就是执行的system/bin/reboot
int main(int argc, char* argv[]) {
int ret;
size_t prop_len;
char property_val[PROPERTY_VALUE_MAX];
static const char reboot[] = "reboot";
const char* cmd = reboot;
char* optarg = "";
opterr = 0;
do {
int c;
c = getopt(argc, argv, "p");
if (c == -1) {
break;
}
switch (c) {
case 'p':
cmd = "shutdown";
break;
case '?':
fprintf(stderr, "usage: %s [-p] [rebootcommand]\n", argv[0]);
exit(EXIT_FAILURE);
}
} while (1);
if(argc > optind + 1) {
fprintf(stderr, "%s: too many arguments\n", argv[0]);
exit(EXIT_FAILURE);
}
if (argc > optind)
optarg = argv[optind];
if (!optarg || !optarg[0]) optarg = "shell";
prop_len = snprintf(property_val, sizeof(property_val), "%s,%s", cmd, optarg);
if (prop_len >= sizeof(property_val)) {
fprintf(stderr, "%s command too long: %s\n", cmd, optarg);
exit(EXIT_FAILURE);
}
ret = property_set(ANDROID_RB_PROPERTY, property_val);
if (ret < 0) {
perror(cmd);
exit(EXIT_FAILURE);
}
// Don't return early. Give the reboot command time to take effect
// to avoid messing up scripts which do "adb shell reboot && adb wait-for-device"
if (cmd == reboot) {
while (1) {
pause();
}
}
fprintf(stderr, "Done\n");
return 0;
}
这里我们主要看ret = property_set(ANDROID_RB_PROPERTY, property_val);
#define ANDROID_RB_PROPERTY “sys.powerctl”
即设置了属性值sys.powerctl为“reboot,adb”或者“reboot,shell”或者“shutdown,shell”或者“reboot,-p”
“reboot,adb”,表示在adb中输入adb reboot进行重启
“reboot,shell”,表示在shell中输入reboot进行重启
“shutdown,shell”,表示在shell中输入reboot -p进行关机
“reboot,-p”,表示在adb中输入adb reboot -p进行关机
system/core/init/init.cpp
void property_changed(const std::string& name, const std::string& value) {
// If the property is sys.powerctl, we bypass the event queue and immediately handle it.
// This is to ensure that init will always and immediately shutdown/reboot, regardless of
// if there are other pending events to process or if init is waiting on an exec service or
// waiting on a property.
// In non-thermal-shutdown case, 'shutdown' trigger will be fired to let device specific
// commands to be executed.
if (name == "sys.powerctl") {
//property_set("vendor.reboot", "reboot");
// Despite the above comment, we can't call HandlePowerctlMessage() in this function,
// because it modifies the contents of the action queue, which can cause the action queue
// to get into a bad state if this function is called from a command being executed by the
// action queue. Instead we set this flag and ensure that shutdown happens before the next
// command is run in the main init loop.
// TODO: once property service is removed from init, this will never happen from a builtin,
// but rather from a callback from the property service socket, in which case this hack can
// go away.
shutdown_command = value;
do_shutdown = true;
}
if (property_triggers_enabled) ActionManager::GetInstance().QueuePropertyChange(name, value);
if (waiting_for_prop) {
if (wait_prop_name == name && wait_prop_value == value) {
LOG(INFO) << "Wait for property took " << *waiting_for_prop;
ResetWaitForProp();
}
}
}
property_changed中监听了系统属性的变化,并且在sys.powerctl属性变化时,将do_shutdown = true;
我们再来看main函数中的执行:
int main(int argc, char** argv) {
while (true) {
// By default, sleep until something happens.
int epoll_timeout_ms = -1;
if (do_shutdown && !shutting_down) {
do_shutdown = false;
//modify by sunxiaolin 20191030
LOG(INFO) << "sunxiaolin,init,sys.powerctl reboot or shutdown sleep(5000)!";
property_set("vendor.reboot", "reboot");
if (!(waiting_for_prop || Service::is_exec_service_running())) {
//LOG(INFO) << "sunxiaolin,init,ExecuteOneCommand!";
am.ExecuteOneCommand();
}
sleep(3);
if (HandlePowerctlMessage(shutdown_command)) {
shutting_down = true;
}
}
//modify by sunxiaolin 20191105
if (!(waiting_for_prop || Service::is_exec_service_running())) {
am.ExecuteOneCommand();
}
}
}
如果收到sys.powerctl属性的变化,条件do_shutdown && !shutting_down得到满足,将执行:
HandlePowerctlMessage
system\core\init\reboot.cpp
bool HandlePowerctlMessage(const std::string& command) {
unsigned int cmd = 0;
std::vector<std::string> cmd_params = Split(command, ",");
std::string reboot_target = "";
bool run_fsck = false;
bool command_invalid = false;
if (cmd_params.size() > 3) {
command_invalid = true;
} else if (cmd_params[0] == "shutdown") {
cmd = ANDROID_RB_POWEROFF;
if (cmd_params.size() == 2) {
if (cmd_params[1] == "userrequested") {
// The shutdown reason is PowerManager.SHUTDOWN_USER_REQUESTED.
// Run fsck once the file system is remounted in read-only mode.
run_fsck = true;
} else if (cmd_params[1] == "thermal") {
// Turn off sources of heat immediately.
TurnOffBacklight();
// run_fsck is false to avoid delay
cmd = ANDROID_RB_THERMOFF;
}
}
} else if (cmd_params[0] == "reboot") {
cmd = ANDROID_RB_RESTART2;
if (cmd_params.size() >= 2) {
reboot_target = cmd_params[1];
// When rebooting to the bootloader notify the bootloader writing
// also the BCB.
if (reboot_target == "bootloader") {
std::string err;
if (!write_reboot_bootloader(&err)) {
LOG(ERROR) << "reboot-bootloader: Error writing "
"bootloader_message: "
<< err;
}
} else if (reboot_target == "recovery") {
std::string err;
if (!write_reboot_recovery(&err)) {
LOG(ERROR) << "reboot-recovery: Error writing "
"recovery_message: "
<< err;
}
}
// If there is an additional parameter, pass it along
if ((cmd_params.size() == 3) && cmd_params[2].size()) {
reboot_target += "," + cmd_params[2];
}
}
} else {
command_invalid = true;
}
if (command_invalid) {
LOG(ERROR) << "powerctl: unrecognized command '" << command << "'";
return false;
}
LOG(INFO) << "Clear action queue and start shutdown trigger";
ActionManager::GetInstance().ClearQueue();
// Queue shutdown trigger first
ActionManager::GetInstance().QueueEventTrigger("shutdown");
// Queue built-in shutdown_done
auto shutdown_handler = [cmd, command, reboot_target, run_fsck](const BuiltinArguments&) {
DoReboot(cmd, command, reboot_target, run_fsck);
return Success();
};
ActionManager::GetInstance().QueueBuiltinAction(shutdown_handler, "shutdown_done");
// Skip wait for prop if it is in progress
ResetWaitForProp();
// Clear EXEC flag if there is one pending
for (const auto& s : ServiceList::GetInstance()) {
s->UnSetExec();
}
return true;
}
编译
在system/core/init下面mm,生成symbols/init
调试
直接push到根目录生效
adb push Z:\imx8_p9.0.0_2.1.0_auto_ga\android9.0.0\out\target\product\mek_8q\symbols\init /