Android 启动过程简析(一)之 init 进程

问题

在进入到 Android 启动过程之前先让我们思考以下几个问题 1. Android 系统的启动过程是怎样的? 2. init 、zygote 进程是什么?在系统启动的过程中各自发挥了什么作用? 3. AMS、PMS 等这些服务是如何被启动的? 4. Launcher 是如何被启动的?

此篇文章将针对 init 部分给出分析

启动流程简述

在了解 init 部分之前,首先简单介绍下系统的启动流程以便抓住主线,当我们通过电源键开启系统的时候,系统首先会加载 bootloader 程序到 RAM 中,然后通过 bootloader 将内核程序加载到 RAM 中,之后内核程序会创建init 进程,在 init 进程中会创建 zygote 进程,而 zygote 进程则会创建 DVM 并且启动 SystemServer 进程,通过SystemServer 系统会启动一系列的服务,包括常见的 AMS、PMS 等,最后再通过 AMS 进入到我们熟知的 Launcher 程序。 所以整个流程的关键点在于 init 进程如何创建 zygote、zygote 进程如何创建 SystemServer、SystemServer 进程如何启动 AMS、AMS 如何启动 Launcher。

init 启动流程分析

由于 bootloader 和内核不是关心的重点,所以这里只是简单介绍它们的作用。

加载运行 BootLoader

在电源上电之后,CPU 中的操作控制器将发出控制信号,将程序计数器(PC)的内容送至地址寄存器(AR),之后启动对主存的读操作,最终将 BootLoader 加载到 RAM 当中。然后 BootLoader 开始执行,主要负责硬件的初始化,将内核程序加载到内存。

init 进程的启动

内核启动之后将会初始化软硬件环境,加载驱动程序,挂载根文件系统,然后创建 init 进程,init 作为系统中的第一个用户进程,其进程号为 1,在创建 init 进程之时,系统会执行位于 system/core/init 下的 init.cpp 程序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
int main(int argc, char** argv) {
...
//创建用户空间目录并挂载
if (is_first_stage) {
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));
mount("sysfs", "/sys", "sysfs", 0, NULL);
}

...

signal_handler_init();

property_load_boot_defaults();
export_oem_lock_status();
//启动属性服务
start_property_service();

...

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

Parser& parser = Parser::GetInstance();
parser.AddSectionParser("service",std::make_unique<ServiceParser>());
parser.AddSectionParser("on", std::make_unique<ActionParser>());
parser.AddSectionParser("import", std::make_unique<ImportParser>());
//解析 init.rc 文件
parser.ParseConfig("/init.rc");
...
return 0;
}

可以看到 init 进程主要做了三件事情:创建用户空间文件夹并挂载、启动属性服务、解析位于 system文件夹下的 init.rc 文件。 这里我们主要关注解析 init.rc 文件的过程,因为 zygote 进程就是在这个过程中创建的。

Android Init Language

由于 init.rc 是一个用 Android 初始化语言(AIL)编写的文件,为了更好的理解 rc 文件的解析过程需要了解一部分 AIL 语法。 AIL 主要有五种类型语句 Actions、Commands、Services、Options、Imports,在 AIL 中每个部分(语句块)表示为一个 Section,比如:

1
2
3
4
on boot
ifup lo
hostname localhost
domainname localdomain

五种语句中只有 Actions、Services、Import 可以用于确定一个 Section。其中 Actions 由一系列 command 组成,Actions 拥有一个 trigger 用于确定何时执行这些命令。

1
2
3
4
5
6
7
8
on <trigger>
<command>
<command>
<command>

on early-init //触发器 early-init
write /proc/1/oom_score_adj -1000 //command
write /proc/sys/kernel/sysrq 0

Services 由一些 option 组成,其在初始化的时候启动,并可以在退出后重启(可选)。

1
2
3
4
5
6
7
8
service <name> <pathname> [ <argument> ]*  //服务名、执行路径、参数
<option>
<option>

service ueventd /sbin/ueventd
class core
critical
seclabel u:r:ueventd:s0

Services 定义了自身的服务名、执行路径以及执行时传入的参数,option 用于指定何时和怎样启动 service,关于何时启动这里进行一下说明,Actions 中有一条命令是 class_start <服务类别名> 用于启动所有未运行的相同类别的 service,而 option 可以通过 class <类别名> 对 service 的类别名进行指定。所以 service 的启动一般是通过 action 触发之后执行 class_start 命令进行启动的。 AIL 的介绍就到这了,如果想要详细了解请阅读 system/core/init 下的 readme.txt 文件

init.rc 解析

system/core/rootdir/init.rc 现在接着分析 init.rc 文件,在文件的首部可以看到

1
2
3
4
5
import /init.environ.rc
import /init.usb.rc
import /init.${ro.hardware}.rc
import /init.usb.configfs.rc
import /init.${ro.zygote}.rc

在这里可以看到需要启动的 zygote,但是与其它引入的 rc 文件相比 zygote 部分并没有使用确定的值,而是使用 ${ro.zygote} 变量去替代,这是因为从 Android 在 5.0 以后开始支持 64 位程序,所以需要根据系统中 ro.zygote 属性的值动态引入。ro.zygote 的值可以通过 adb shell getprop 进行查询,我的手机查询结果是:

这说明手机会启动两个 zygote 进程,对应的执行程序分别是 app_process64 (主模式)、app_process32,通过 adb shell ps | grep zygote 可以看到确实存在两个 zygote 进程

接着查看与 init.rc 同一目录下的 init.zygote64_32.rc 文件 system/core/rootdir/init.zygote64_32.rc

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server --socket-name=zygote
class main
socket zygote stream 660 root system
onrestart write /sys/android_power/request_state wake
onrestart write /sys/power/state on
onrestart restart audioserver
onrestart restart cameraserver
onrestart restart media
onrestart restart netd
writepid /dev/cpuset/foreground/tasks /sys/fs/cgroup/stune/foreground/tasks

service zygote_secondary /system/bin/app_process32 -Xzygote /system/bin --zygote --socket-name=zygote_secondary
class main
socket zygote_secondary stream 660 root system
onrestart restart zygote
writepid /dev/cpuset/foreground/tasks /dev/stune/foreground/tasks

前文说过 service 的启动和类别名相关,这里两个 zygote service 的类别名都是 main,所以要想知道 zygote 怎么被启动的我们可以在 init.rc 中搜索 class_start main,可以发现

1
2
3
4
5
on nonencrypted
# A/B update verifier that marks a successful boot.
exec - root -- /system/bin/update_verifier nonencrypted
class_start main
class_start late_start

从这里我们可以了解到当 nonencrypted 这个触发器被触发的时候 zygote 就会被启动,所以启动 zygote 的问题就转变为这个触发器什么时候执行?class_start 对应的处理函数是什么?要想知道答案,必须回到 init.cpp 的解析过程当中

1
2
3
4
5
Parser& parser = Parser::GetInstance();
parser.AddSectionParser("service",std::make_unique<ServiceParser>());
parser.AddSectionParser("on", std::make_unique<ActionParser>());
parser.AddSectionParser("import", std::make_unique<ImportParser>());
parser.ParseConfig("/init.rc");

init.rc 交由一个 Parser 对象进行解析,而 Parser 的实现在 system/core/init/init_parser.cpp 文件中,让我们进入到 init_parser.cpp 中查看 AddSectionParser 的实现

1
2
3
4
5
6
7
void Parser::AddSectionParser(const std::string& name,
std::unique_ptr<SectionParser> parser) {
section_parsers_[name] = std::move(parser);
}

//init_parser.h 中 section_parsers_ 的定义
std::map<std::string, std::unique_ptr<SectionParser>> section_parsers_;

可以看到每一个 parser 最终被保存在 section_parsers_ 中,section_parsers_ 是什么?查看 init_parser.h 中的定义可以知道,section_parsers_ 是一个 map 集合,所以 section_parsers_ 的作用是将 parser 与对应的 Section 进行绑定。 在添加完所有的 parser 之后就会调用 Parser 的 ParseConfig 方法

1
2
3
4
5
6
bool Parser::ParseConfig(const std::string& path) {
if (is_dir(path.c_str())) {
return ParseConfigDir(path);
}
return ParseConfigFile(path);
}

ParseConfig 中会对 path 进行判断,如果是目录则调用 ParseConfigDir 进行递归然后再通过 ParseConfigFile 进行解析。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
bool Parser::ParseConfigDir(const std::string& path) {
INFO("Parsing directory %s...\n", path.c_str());
std::unique_ptr<DIR, int(*)(DIR*)> config_dir(opendir(path.c_str()), closedir);
if (!config_dir) {
ERROR("Could not import directory '%s'\n", path.c_str());
return false;
}
dirent* current_file;
while ((current_file = readdir(config_dir.get()))) {
std::string current_path =
android::base::StringPrintf("%s/%s", path.c_str(), current_file->d_name);
// Ignore directories and only process regular files.
if (current_file->d_type == DT_REG) {
if (!ParseConfigFile(current_path)) { //调用 ParseConfigFile 进行解析
ERROR("could not import file '%s'\n", current_path.c_str());
}
}
}
return true;
}

最终在 ParseConfigFile 中通过 ParseData 进行解析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
bool Parser::ParseConfigFile(const std::string& path) {
INFO("Parsing file %s...\n", path.c_str());
Timer t;
std::string data;
//从 rc 文件中读取内容保存在 data 中
if (!read_file(path.c_str(), &data)) {
return false;
}

data.push_back('\n'); // TODO: fix parse_config.
ParseData(path, data); //调用 ParseData 进行解析
...
return true;
}

ParseData 解析过程如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
void Parser::ParseData(const std::string& filename, const std::string& data) {
//TODO: Use a parser with const input and remove this copy
std::vector<char> data_copy(data.begin(), data.end()); //将 rc 中的内容保存在 vector 中便于逐个字符进行解析
data_copy.push_back('\0');

parse_state state;
state.filename = filename.c_str();
state.line = 0;
state.ptr = &data_copy[0];
state.nexttoken = 0;

SectionParser* section_parser = nullptr;
std::vector<std::string> args; //存放的是每行的内容

for (;;) {
switch (next_token(&state)) {
case T_EOF:
if (section_parser) {
section_parser->EndSection();
}
return;
case T_NEWLINE:
state.line++;
//如果 args 为空则不进行解析(rc 文件中间存在空行,所以需要判断)
if (args.empty()) {
break;
}
//判断是不是一个 section 的起始位置(通过能不能获得解析器,可以判断 args[0] 是不是 service、on、import 其中一个)
if (section_parsers_.count(args[0])) {
if (section_parser) {
//如果上次存在解析则结束解析
section_parser->EndSection();
}
//取出对应的解析器
section_parser = section_parsers_[args[0]].get();
std::string ret_err;
//进行 Section 解析
if (!section_parser->ParseSection(args, &ret_err)) {
parse_error(&state, "%s\n", ret_err.c_str());
section_parser = nullptr;
}
} else if (section_parser) { //不是的话说明 args 中是一个 section 的子块,则进行 Line 解析
std::string ret_err;
if (!section_parser->ParseLineSection(args, state.filename,
state.line, &ret_err)) {
parse_error(&state, "%s\n", ret_err.c_str());
}
}
//解析完成后清空
args.clear();
break;
case T_TEXT:
args.emplace_back(state.text);
break;
}
}
}

ParseData 中通过调用 system/core/init/parser.cpp 中的 next_token 函数对 rc 内容进行分析,如果是 T_TEXT 则会保存在 args 中,如果是 T_NEWLINE 则会交由对应的解析器进行解析。init.rc 的大致解析过程如此,但是到这里我们依旧没能找到所需要的答案,所以需要继续查看 ActionParser 和 ServiceParser 的解析过程。

ActionParser 解析过程

ActionParser 位于 system/core/init/action.cpp 中,从前面的解析过程来看,最后的解析总是调用了对应 parser 的 ParseSection、ParseLineSection 以及 EndSection,所以我们主要看下这两个部分 ParseSection 的主要工作是创建 Action 对象,为对象添加触发器,并将 action_ 移动至当前 Action 对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
bool ActionParser::ParseSection(const std::vector<std::string>& args,
std::string* err) {
std::vector<std::string> triggers(args.begin() + 1, args.end());
...

auto action = std::make_unique<Action>(false);
//为 action 增加触发器
if (!action->InitTriggers(triggers, err)) {
return false;
}

//将 aciton_ 指针移动到当前的 action
action_ = std::move(action);
return true;
}

//action_ 在 action.h 中的定义
private:
std::unique_ptr<Action> action_;

ParseLineSection 的主要工作为查找对应 command 的处理函数,将创建的 Command 对象添加到到commands_,由于 commands_ 是 Action 的一个域,所以实际上 ParseLineSection 在填充当前 Action 对象的域。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
bool ActionParser::ParseLineSection(const std::vector<std::string>& args,
const std::string& filename, int line,
std::string* err) const {
//将解析的 command 增加到当前 action 的 commands_ 中
return action_ ? action_->AddCommand(args, filename, line, err) : false;
}

bool Action::AddCommand(const std::vector<std::string>& args,
const std::string& filename, int line, std::string* err) {
...
//查找对应的 command 的处理函数
auto function = function_map_->FindFunction(args[0], args.size() - 1, err);
if (!function) {
return false;
}

AddCommand(function, args, filename, line);
return true;
}

void Action::AddCommand(BuiltinFunction f,
const std::vector<std::string>& args,
const std::string& filename, int line) {
//commands_ 增加 command 和对应的处理函数
commands_.emplace_back(f, args, filename, line);
}

//commands_ 在 action.h 中的定义
std::vector<Command> commands_;

//Command 在 action.h 中的定义
class Command {
public:
Command(BuiltinFunction f, const std::vector<std::string>& args,
const std::string& filename, int line);

int InvokeFunc() const;
std::string BuildCommandString() const;
std::string BuildSourceString() const;

private:
BuiltinFunction func_;
std::vector<std::string> args_;
std::string filename_;
int line_;
};

EndSection 的主要工作是将解析完成的 action (域填充完毕的 Action 对象)添加到 ActionManager 的 acitons_ 中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
void ActionParser::EndSection() {
if (action_ && action_->NumCommands() > 0) {
ActionManager::GetInstance().AddAction(std::move(action_));
}
}

void ActionManager::AddAction(std::unique_ptr<Action> action) {
...

if (old_action_it != actions_.end()) {
(*old_action_it)->CombineAction(*action);
} else {
//将解析之后的 action 对象增加到 actions_ 链表中,用于遍历执行。
actions_.emplace_back(std::move(action));
}
}

//ActionManager 在 action.h 中的定义
class ActionManager {
public:
static ActionManager& GetInstance();

void AddAction(std::unique_ptr<Action> action);
void QueueEventTrigger(const std::string& trigger);
void QueuePropertyTrigger(const std::string& name, const std::string& value);
void QueueAllPropertyTriggers();
void QueueBuiltinAction(BuiltinFunction func, const std::string& name);
void ExecuteOneCommand();
bool HasMoreCommands() const;
void DumpState() const;

private:
ActionManager();

ActionManager(ActionManager const&) = delete;
void operator=(ActionManager const&) = delete;

std::vector<std::unique_ptr<Action>> actions_; //actions_ 的定义
std::queue<std::unique_ptr<Trigger>> trigger_queue_;
std::queue<const Action*> current_executing_actions_;
std::size_t current_command_;
};

通过以上分析我们能够知道 class_start 的处理函数和 function_map_ 相关,查看 function_map_ 在 action.h 中的定义可以看到

1
2
3
4
5
static const KeywordMap<BuiltinFunction>* function_map_;

static void set_function_map(const KeywordMap<BuiltinFunction>* function_map) {
function_map_ = function_map;
}

所以要想知道处理函数是什么只需要知道 set_function_map 在哪里调用?让我们再次回到 init.cpp 中,可以看到

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

接下来需要找到 BuiltinFunctionMap,BuiltinFunctionMap 的实现我们可以在 builtins.cpp 中找到,其具体的实现 system/core/init/builtins.cpp

1
2
3
4
5
6
7
8
9
10
BuiltinFunctionMap::Map& BuiltinFunctionMap::map() const {
constexpr std::size_t kMax = std::numeric_limits<std::size_t>::max();
static const Map builtin_functions = {
...
{"class_start", {1, 1, do_class_start}},
{"class_stop", {1, 1, do_class_stop}},
...
};
return builtin_functions;
}

到这里就可以确定 class_start 对应的处理函数是 do_class_start,do_class_start 也可在 builtins.cpp 中找到。 简单总结下解析 Action 的过程,实际上是创建一个 Action 对象,然后为 Action 对象添加 Trigger 以及对应的 Command,其中在添加 Command 的过程中还为 Command 指定了处理函数,最后在将 Action 对象增加到 ActionManager vector 类型的 actions_ 链表当中去。

ServiceParser 解析过程

与前文一致,接着看那三个函数 ParseSection 的主要工作是创建 Service 对象,将 service_ 移动至当前 Service 对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
bool ServiceParser::ParseSection(const std::vector<std::string>& args,
std::string* err) {
...
//获取服务名
const std::string& name = args[1];
...
//保存服务名外的参数(如执行路径等)
std::vector<std::string> str_args(args.begin() + 2, args.end());
//将 service_ 指针指向当前 Service 对象
service_ = std::make_unique<Service>(name, "default", str_args);
return true;
}

//service_ 在 service.h 中的定义
std::unique_ptr<Service> service_;

ParseLineSection 的主要工作是为 Service 中每个 option 指定处理函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
bool ServiceParser::ParseLineSection(const std::vector<std::string>& args,
const std::string& filename, int line,
std::string* err) const {
//为 Service 中的每一个 Option 指定处理函数
return service_ ? service_->HandleLine(args, err) : false;
}

bool Service::HandleLine(const std::vector<std::string>& args, std::string* err) {
...

static const OptionHandlerMap handler_map;
//寻找对应 option 的处理函数
auto handler = handler_map.FindFunction(args[0], args.size() - 1, err);

...

return (this->*handler)(args, err);
}

EndSection 的主要工作是将解析完成的 service (域填充完毕的 Service 对象)添加到 ServiceManager 的 services_ 中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
void ServiceParser::EndSection() {
if (service_) {
ServiceManager::GetInstance().AddService(std::move(service_));
}
}

void ServiceManager::AddService(std::unique_ptr<Service> service) {
Service* old_service = FindServiceByName(service->name());
if (old_service) {
ERROR("ignored duplicate definition of service '%s'",
service->name().c_str());
return;
}
//将解析之后 service 对象增加到 services_ 链表中
services_.emplace_back(std::move(service));
}

//ServiceManager 在 service.h 中的定义
class ServiceManager {
public:
static ServiceManager& GetInstance();

void AddService(std::unique_ptr<Service> service);
Service* MakeExecOneshotService(const std::vector<std::string>& args);
Service* FindServiceByName(const std::string& name) const;
Service* FindServiceByPid(pid_t pid) const;
Service* FindServiceByKeychord(int keychord_id) const;
void ForEachService(std::function<void(Service*)> callback) const;
void ForEachServiceInClass(const std::string& classname,
void (*func)(Service* svc)) const;
void ForEachServiceWithFlags(unsigned matchflags,
void (*func)(Service* svc)) const;
void ReapAnyOutstandingChildren();
void RemoveService(const Service& svc);
void DumpState() const;

private:
ServiceManager();
bool ReapOneProcess();
static int exec_count_; // Every service needs a unique name.
std::vector<std::unique_ptr<Service>> services_; //services_ 的定义
};

对应的可以看下 option 的处理函数,虽然 OptionHandlerMap 与启动 zygote 无关,但是还是看下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
Service::OptionHandlerMap::Map& Service::OptionHandlerMap::map() const {
constexpr std::size_t kMax = std::numeric_limits<std::size_t>::max();
static const Map option_handlers = {
{"class", {1, 1, &Service::HandleClass}},
{"console", {0, 0, &Service::HandleConsole}},
{"critical", {0, 0, &Service::HandleCritical}},
{"disabled", {0, 0, &Service::HandleDisabled}},
{"group", {1, NR_SVC_SUPP_GIDS + 1, &Service::HandleGroup}},
{"ioprio", {2, 2, &Service::HandleIoprio}},
{"keycodes", {1, kMax, &Service::HandleKeycodes}},
{"oneshot", {0, 0, &Service::HandleOneshot}},
{"onrestart", {1, kMax, &Service::HandleOnrestart}},
{"seclabel", {1, 1, &Service::HandleSeclabel}},
{"setenv", {2, 2, &Service::HandleSetenv}},
{"socket", {3, 6, &Service::HandleSocket}},
{"user", {1, 1, &Service::HandleUser}},
{"writepid", {1, kMax, &Service::HandleWritepid}},
};
return option_handlers;
}

与解析 Action 类似,在整个过程中先创建 Service 对象,解析出 Service 的名字和对应的参数添加到对象当中,并且给每个 Option 指定了相应的处理函数 到这里 rc 文件的解析就结束了,通过 rc 文件的解析使得每个 action 都有了对应的执行函数,所以接下来的问题是这些 action 是如何被触发的(也即是 command 命令是如何被执行的)?

Actions 的触发

让我们继续回到 init.cpp 中

1
2
3
4
5
6
7
8
9
10
ActionManager& am = ActionManager::GetInstance();
....

while (true) {
if (!waiting_for_exec) {
am.ExecuteOneCommand();
restart_processes();
}
...
}

可以看到 action 的 command 的执行是通过 ActionManager 的 ExecuteOneCommand 函数,而ActionManager 的 ExecuteOneCommand 最终调用了 Action 的 ExecuteOneCommand system/core/init/action.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
void ActionManager::ExecuteOneCommand() {
//循环等待,直到队列中不为空
while (current_executing_actions_.empty() && !trigger_queue_.empty()) {
//遍历 actions_
for (const auto& action : actions_) {
if (trigger_queue_.front()->CheckTriggers(*action)) {
//将 action 加入到 current_executing_actions_ 中
current_executing_actions_.emplace(action.get());
}
}
trigger_queue_.pop();
}

...

//每次只执行一个 action
auto action = current_executing_actions_.front();

if (current_command_ == 0) {
std::string trigger_name = action->BuildTriggersString();
INFO("processing action (%s)\n", trigger_name.c_str());
}

//执行 action 的 command
action->ExecuteOneCommand(current_command_);

++current_command_;
...
}

void Action::ExecuteOneCommand(std::size_t command) const {
//执行 action 对象中保存的 command
ExecuteCommand(commands_[command]);
}

void Action::ExecuteCommand(const Command& command) const {
Timer t;
//调用 command 对应的处理函数
int result = command.InvokeFunc();

...
}

通过上述分析可以知道,init 进程最终进入到无限循环中,然后按照 ActionManager 中 actions_ 保存的 action 顺序依次对每个 Action 进行处理,而在这个过程中 system/core/init/builtins.cpp 下用于启动 zygote 的 do_class_start 函数将会被执行

1
2
3
4
5
static int do_class_start(const std::vector<std::string>& args) {
ServiceManager::GetInstance().
ForEachServiceInClass(args[1], [] (Service* s) { s->StartIfNotDisabled(); });
return 0;
}

do_class_start 函数中调用 Service 的 StartIfNotDisabled,StartIfNotDisabled 在 service.cpp 的实现如下

1
2
3
4
5
6
7
8
bool Service::StartIfNotDisabled() {
if (!(flags_ & SVC_DISABLED)) {
return Start();
} else {
flags_ |= SVC_DISABLED_START;
}
return true;
}

StartIfNotDisabled 最终调用了 Service 的 Start 函数,Start 函数创建了 zygote 的进程,并且执行了 init.zygote64_32.rc 中定义的执行路径下的文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
bool Service::Start() {
....
//创建子进程
pid_t pid = fork();
if (pid == 0) {
...
//执行对应 service 对应的执行文件,args_[0].c_str() 就是执行路径
if (execve(args_[0].c_str(), (char**) &strs[0], (char**) ENV) < 0) {
ERROR("cannot execve('%s'): %s\n", args_[0].c_str(), strerror(errno));
}

_exit(127);
}

....
return true;
}

在完成这一切之后将会进入 frameworks/base/cmds/app_process/app_main.cpp 中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
int main(int argc, char* const argv[])
{
....

if (zygote) {
//启动 zygote
runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
} else if (className) {
runtime.start("com.android.internal.os.RuntimeInit", args, zygote);
} else {
fprintf(stderr, "Error: no class name or --zygote supplied.\n");
app_usage();
LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
return 10;
}
}

可以看到 zygote 最终在 app_main 的 main 函数中被启动。

总结

到这里我们就能够回答对 init 部分相关的问题了 1. init 的作用 init 是系统中的第一个用户进程,它的主要作用是创建用户空间文件夹并挂载、启动属性服务、解析 init.rc 文件并启动 zygote 进程。 2. init 启动 zygote 的过程 init 进程通过解析 init.rc 文件将 action 保存在 ActionManager 的 actions_ 链表中,然后通过遍历 actions_ 链表,执行 action 命令对应的处理函数,从而转至 builtins.cpp 的 do_class_start 函数,之后通过 Service 的 StartIfNotDisabled 调用 Service 的 Start 函数,最终通过 Start 函数创建 zygote 进程,执行对应的 app_main.cpp 文件启动 zygote。

Thanks

  1. Android7.0 init进程源码分析
  2. Android Init Language(android初始化语言)
  3. Android系统启动流程(一)解析init进程启动过程