在Linux系统中,Kernel启动完毕之后,启动的第一个用户空间的进程,就是名为init的进程:

以下是查找init进程源码的过程:

  1. 查找init进程mk文件位置:

    查找可执行程序:init的编译MODULE定义,即全局查找字符串: LOCAL_MODULE:= init,从而找到mk文件位置system/core/init/Android.mk

  2. 从MODULE的LOCAL_SRC_FILES找到init.cpp文件

  3. 全局查找文件(按两次)init.cpp,从而最终找到init.cpp的源码system/core/init/init.cpp

init启动解析: main函数

作为init可执行文件的入口init.cpp->main(),我们来看下它是怎么执行的

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
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
int main(int argc, char** argv) {
...
// 将/usr/bin:/bin加入到环境变量中去
add_environment("PATH", _PATH_DEFPATH);
bool is_first_stage = (argc == 1) || (strcmp(argv[1], "--second-stage") != 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.
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);
}
...
// Set up SELinux, including loading the SELinux policy if we're in the kernel domain.
selinux_initialize(is_first_stage);
...
// These directories were necessarily created before initial policy load
// and therefore need their security context restored to the proper value.
// This must happen before /dev is populated by ueventd.
NOTICE("Running restorecon...\n");
restorecon("/dev");
restorecon("/dev/socket");
restorecon("/dev/__properties__");
restorecon("/property_contexts");
restorecon_recursive("/sys");
epoll_fd = epoll_create1(EPOLL_CLOEXEC);
...
//信号处理handler初始化:通过信号量,管理init fork出来的子进程
signal_handler_init();
//导入默认boot_property
property_load_boot_defaults();
//导入oem锁状态
export_oem_lock_status();
//属性服务初始化
start_property_service();
//创建内建的函数映射key-func的map集合,Action解析触发都依赖与该map查找对应的函数
const BuiltinFunctionMap function_map;
Action::set_function_map(&function_map);
//init.rc文件的解析
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");
ActionManager& am = ActionManager::GetInstance();
...
// init进程进入该循环
// 1. 执行am的命令
// 2. 重启相关的process,这里其实是我们通过service启动的子进程
while (true) {
if (!waiting_for_exec) {
am.ExecuteOneCommand();
restart_processes();
}
int timeout = -1;
if (process_needs_restart) {
timeout = (process_needs_restart - gettime()) * 1000;
if (timeout < 0)
timeout = 0;
}
if (am.HasMoreCommands()) {
timeout = 0;
}
bootchart_sample(&timeout);
//阻塞,等待新的command的到来
epoll_event ev;
int nr = TEMP_FAILURE_RETRY(epoll_wait(epoll_fd, &ev, 1, timeout));
if (nr == -1) {
ERROR("epoll_wait failed: %s\n", strerror(errno));
} else if (nr == 1) {
((void (*)()) ev.data.ptr)();
}
}
return 0;
}

总结下来,init进程做了几件事情:

  1. bin环境变量的添加
  2. 所需的文件系统的挂载
  3. 信号处理、oem锁、属性服务启动
  4. init.rc文件的解析
  5. 进入循环,通过ActionManager开始执行Command
  6. restart_processes,重新启动process,如果有必要的话

本文,我们只关注两点:

  1. rc文件的解析
  2. restart_processes 启动新的process

init.rc文件的解析过程

init.rc文件位于system/core/rootdir/init.rc

rc文件的变化

在 7.+ 版本的系统中,rc文件的内容根据具体的模块拆分成不同的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

又比如servicemanager的初始化: frameworks/native/cmds/servicemanager/servicemanager.rc

参考链接:http://blog.csdn.net/sunao2002002/article/details/52454878

解析源码段分析

先来看看代码段

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");

  1. Parser是一个单例,全局字符串查找 Parser::GetInstance,即可找到定义位置system/core/init/init_parser.cpp

    1
    2
    3
    4
    Parser& Parser::GetInstance() {
    static Parser instance;
    return instance;
    }
  2. 调用AddSectionParser将几个解析器放置到map中:

    1
    2
    3
    4
    void Parser::AddSectionParser(const std::string& name,
    std::unique_ptr<SectionParser> parser) {
    section_parsers_[name] = std::move(parser);
    }
  3. 开始解析:parser.ParseConfig("/init.rc");

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

由于传入的”/init.rc”是一个文件,因此开始ParseConfigFile(path)解析

  1. file解析
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    bool Parser::ParseConfigFile(const std::string& path) {
    INFO("Parsing file %s...\n", path.c_str());
    Timer t;
    std::string data;
    //将file内容读入data字符串中
    if (!read_file(path.c_str(), &data)) {
    return false;
    }
    //内容字符串修正
    data.push_back('\n'); // TODO: fix parse_config.
    //4.1 解析文件内容
    ParseData(path, data);
    for (const auto& sp : section_parsers_) {
    //4.2 解析文件完毕
    sp.second->EndFile(path);
    }
    // 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();
    NOTICE("(Parsing %s took %.2fs.)\n", path.c_str(), t.duration());
    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
58
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());
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 (;;) {
//next_token():真正解析文件的地方
switch (next_token(&state)) {
case T_EOF:
//解析到文件末尾
if (section_parser) {
section_parser->EndSection();
}
return;
case T_NEWLINE:
//新行
state.line++;
if (args.empty()) {
break;
}
if (section_parsers_.count(args[0])) {
//新的一行开始,如果此前的section_parser不为空,则结束那一行的解析:EndSection
if (section_parser) {
section_parser->EndSection();
}
section_parser = section_parsers_[args[0]].get();
std::string ret_err;
if (!section_parser->ParseSection(args, &ret_err)) {
parse_error(&state, "%s\n", ret_err.c_str());
section_parser = nullptr;
}
} else if (section_parser) {
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:
//解析到字符串内容:例如 service zygote /system/bin/app_process
//则解析到的结果是args={"service", "zygote", "/system/bin/app_process"}
args.emplace_back(state.text);
break;
}
}
}

GetInstance

举例说明解析过程

  1. 读取init.rc文件时,遇到import语句,因此args[0] = “import”,采用ImportParser进行解析
  2. 调用ImportParser->ParseSection进行解析:args={“import”, “/init.${ro.zygote}.rc”}

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    bool ImportParser::ParseSection(const std::vector<std::string>& args,
    std::string* err) {
    if (args.size() != 2) {
    *err = "single argument needed for import\n";
    return false;
    }
    std::string conf_file;
    //通过expand_props将${ro.zygote}替换成对应平台的实现,例如zygote32,因此文件名为:init.zygote32.rc
    bool ret = expand_props(args[1], &conf_file);
    if (!ret) {
    *err = "error while expanding import";
    return false;
    }
    INFO("Added '%s' to import list\n", conf_file.c_str());
    //将解析出来,import的真正文件名放到imports_列表中
    imports_.emplace_back(std::move(conf_file));
    return true;
    }
  3. 回到Parser::ParseConfigFile,当文件解析完毕之后,调用所有的Parser->EndFile

    1
    2
    3
    4
    for (const auto& sp : section_parsers_) {
    //4.2 解析文件完毕
    sp.second->EndFile(path);
    }

因此,我们看下ImportParser->EndFile():

1
2
3
4
5
6
7
8
9
10
void ImportParser::EndFile(const std::string& filename) {
auto current_imports = std::move(imports_);
imports_.clear();
for (const auto& s : current_imports) {
if (!Parser::GetInstance().ParseConfig(s)) {
ERROR("could not import file '%s' from '%s': %s\n",
s.c_str(), filename.c_str(), strerror(errno));
}
}
}

由此可见,又针对每个文件,进行了Parser::GetInstance().ParseConfig(s)解析

  1. imprt进来的file的解析步骤仍然走的:

    • Parser::ParseConfig
    • Parser::ParseConfigFile
    • 循环1. Parser::ParseData
    • 循环2. system/core/init/parser.cpp->next_token()
    • 循环3. Parser::ParseSection
    • 循环4. Parser::EndSection
  2. 我们来看service的解析:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
    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
    1. 在ParserData()的时候,args[0]=”service”,采用ServiceParser进行解析
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      bool ServiceParser::ParseSection(const std::vector<std::string>& args,
      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;
      }
      std::vector<std::string> str_args(args.begin() + 2, args.end());
      service_ = std::make_unique<Service>(name, "default", str_args);
      return true;
      }

    由此可见,service关键字的解析,将会创建Service对象,并赋值给ServiceParser的service_成员

    1. 当这一行解析完毕之后,进入下一行,由于下一行的args[0]不为{“service”,”on”,”import”}中的任意一个,因此进入解析方法ParseLineSection
      1
      2
      3
      bool ServiceParser::ParseLineSection(const std::vector<std::string>& args, const std::string& filename, int line, std::string* err) const {
      return service_ ? service_->HandleLine(args, err) : false;
      }

    HandleLine方法

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    bool Service::HandleLine(const std::vector<std::string>& args, std::string* err) {
    if (args.empty()) {
    *err = "option needed, but not provided";
    return false;
    }
    //根据OptionHandlerMap,找寻args[0]所对应的函数
    static const OptionHandlerMap handler_map;
    auto handler = handler_map.FindFunction(args[0], args.size() - 1, err);
    if (!handler) {
    return false;
    }
    //找到args[0]对应的方法,调用该方法,并将方法的返回值true/false,
    //返回: 这些方法基本上都是service_的属性设置,返回的都是boolean值
    return (this->*handler)(args, err);
    }

    //OptionHandlerMap定义如下

    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;
    }
    1. 当所有的Line解析完毕,到达文件末尾,则调用ServiceParser::EndSection方法:
      1
      2
      3
      4
      5
      void ServiceParser::EndSection() {
      if (service_) {
      ServiceManager::GetInstance().AddService(std::move(service_));
      }
      }

    将刚才解析的service_成员,move到ServiceManager的列表中

    1
    2
    3
    4
    5
    6
    7
    8
    9
    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;
    }
    services_.emplace_back(std::move(service));
    }
    1. 至此,init.zygote32.rc文件解析完毕

restart_processes

前面分析init.cpp->main()函数的时候,在while循环中,调用了restart_processes方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
static void restart_processes()
{
process_needs_restart = 0;
ServiceManager::GetInstance().
ForEachServiceWithFlags(SVC_RESTARTING, [] (Service* s) {
s->RestartIfNeeded(process_needs_restart);
});
}
void ServiceManager::ForEachServiceWithFlags(unsigned matchflags,
void (*func)(Service* svc)) const {
for (const auto& s : services_) {
if (s->flags() & matchflags) {
func(s.get());
}
}
}

从代码看到,这段代码对每一个Service,都进行了调用函数调用

1
:s->RestartIfNeeded(process_needs_restart);

因此,最终调用到了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
void Service::RestartIfNeeded(time_t& process_needs_restart) {
time_t next_start_time = time_started_ + 5;
if (next_start_time <= gettime()) {
flags_ &= (~SVC_RESTARTING);
Start();
return;
}
if ((next_start_time < process_needs_restart) ||
(process_needs_restart == 0)) {
process_needs_restart = next_start_time;
}
}

调用到了Service:Start()方法: system/core/init/service.cpp

这段代码比较长,就不贴了,列举几个重要的片段:

  • fork一个新的进程

    1
    pid_t pid = fork();
  • 在新的进程中,如果sockets_不为空,就创建socket: 此处init.zygote32.rc文件中,socket zygote stream 660 root system

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
for (const auto& si : sockets_) {
int socket_type = ((si.type == "stream" ? SOCK_STREAM :
(si.type == "dgram" ? SOCK_DGRAM :
SOCK_SEQPACKET)));
const char* socketcon =
!si.socketcon.empty() ? si.socketcon.c_str() : scon.c_str();
int s = create_socket(si.name.c_str(), socket_type, si.perm,
si.uid, si.gid, socketcon);
if (s >= 0) {
//调用PublishSocket,将si.name=zygote,设置到环境变量"ANDROID_SOCKET_ENV_PREFIX si.name"中去
PublishSocket(si.name, s);
}
}
//最终通过execve来执行 /system/bin/app_process
if (execve(strs[0], (char**) &strs[0], (char**) ENV) < 0) {
ERROR("cannot execve('%s'): %s\n", strs[0], strerror(errno));
}
void Service::PublishSocket(const std::string& name, int fd) const {
std::string key = StringPrintf(ANDROID_SOCKET_ENV_PREFIX "%s", name.c_str());
std::string val = StringPrintf("%d", fd);
add_environment(key.c_str(), val.c_str());
/* make sure we don't close-on-exec */
fcntl(fd, F_SETFD, 0);
}

因此会创建一个名为zygote的socket,挂在在/dev/socket/zygote节点下,

最终通过execve来执行 /system/bin/app_process

至此,一个service进程就解析,并创建进程,在新进程中开始执行

完结

上述分析,仅仅针对service关键字做了分析,其他的关键字on、class等等,同理分析

参考资料: