(N)Telephony分析(一)之zygote进程启动

Android是基于Linux系统的,而init进程是Linux系统的第一进程,因此,需要分析zygote的启动,首先就需要查看init进程的启动

/system/core/init/init.cpp文件

int main(int argc, char** argv) {
    ......
    const BuiltinFunctionMap function_map;
    Action::set_function_map(&function_map);

    Parser& parser = Parser::GetInstance();
    // Leo, 将ServiceParser/ActionParser/ImportParser加入到section_parsers_中,并且关键字分别设置为service/on/import
    parser.AddSectionParser("service",std::make_unique());
    parser.AddSectionParser("on", std::make_unique());
    parser.AddSectionParser("import", std::make_unique());
    // init_parser:; Parser::ParseConfig
    // parse init.rc file
    // Leo,解析init.rc配置文件
    parser.ParseConfig("/init.rc");
    ......
    while (true) {
        if (!waiting_for_exec) {
            am.ExecuteOneCommand();
            // Leo, 启动所有的restart标志的进程
            restart_processes();
        }
        ......
    }
    return 0;
}
可以看到,在init进程的main函数中,主要做了以下的事

1. 解析init.rc文件

2. 启动所有restart标志的进程
下面,主要对这两点分别说明

1. 解析init.rc文件

首先,先查看parser的AddSectionParser方法

void Parser::AddSectionParser(const std::string& name,
                              std::unique_ptr parser) {
    section_parsers_[name] = std::move(parser);
}

因此,此处定义了以service/on/import为关键字的Action,并且分别对应的是ServiceParser/ActionParser/ImportParser的解析器

查看init_parser.cpp文件中的ParseConfig方法

bool Parser::ParseConfig(const std::string& path) {
    if (is_dir(path.c_str())) {
        return ParseConfigDir(path);
    }
    return ParseConfigFile(path);
}
bool Parser::ParseConfigFile(const std::string& path) {
    INFO("Parsing file %s...\n", path.c_str());
    Timer t;
    std::string data;
    if (!read_file(path.c_str(), &data)) {
        return false;
    }

    data.push_back('\n'); // TODO: fix parse_config.
    // Leo, 解析init.rc文件
    ParseData(path, data);
    // Leo,解析文件结束后,调用section_parsers_的EndFile方法
    for (const auto& sp : section_parsers_) {
        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方法,之前调用所有的section_parsers_的EndFile方法

void Parser::ParseData(const std::string& filename, const std::string& data) {
    //TODO: Use a parser with const input and remove this copy
    std::vector 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 args;

    for (;;) {
        switch (next_token(&state)) {
        case T_EOF:
            if (section_parser) {
                section_parser->EndSection();
            }
            return;
        case T_NEWLINE:
            state.line++;
            if (args.empty()) {
                break;
            }
            // Leo,当Action为servoce/on/import的时候,走if分支
            if (section_parsers_.count(args[0])) {
                if (section_parser) {
                    section_parser->EndSection();
                }
                // Leo,设置section_parsers_的值
                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;
                }
            // Leo, 当Action不是service/on/import的时候,走else分支
            } 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:
            args.emplace_back(state.text);
            break;
        }
    }
}
因此,查看init.rc文件,启动zygote的代码为import /init.${ro.zygote}.rc,因此,需要调用的是ImportParser的ParseSection方法

import_parser.cpp文件

bool ImportParser::ParseSection(const std::vector& args,
                                std::string* err) {
    if (args.size() != 2) {
        *err = "single argument needed for import\n";
        return false;
    }


    std::string conf_file;
    // Leo,将args[1],即init.zygote32.rc文件(此处只分析zygote32的配置文件)内容写入到conf_file
    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());
    // Leo,将conf_file的数据,直接保存到import_中
    imports_.emplace_back(std::move(conf_file));
    return true;
}
可以看到,此处是将init.zygote32.rc文件中的数据写入到imports_中

接下来,我们看到init_parser.cpp文件中的ParseConfigFile中,是先调用的ParseData方法,后调用section_parser_的EndFile方法,因此,查看ImportParser中的EndFile方法

import_parser.cpp文件

void ImportParser::EndFile(const std::string& filename) {
    auto current_imports = std::move(imports_);
    imports_.clear();
    for (const auto& s : current_imports) {
    	// Leo,重新调用ParseConfig来解析import_中的数据,即init.zygote32.rc中的数据
        if (!Parser::GetInstance().ParseConfig(s)) {
            ERROR("could not import file '%s' from '%s': %s\n",
                  s.c_str(), filename.c_str(), strerror(errno));
        }
    }
}
可以看到,此处又走到了Parser的ParseConfig方法,而此时,解析的数据为init.zygote32.rc文件中的数据,查看init.zygote32.rc文件中的内容

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
因此,首先解析第一行,action为service,此时关键字为service对应的为ServiceParser解析器,因此

service.cpp文件

bool ServiceParser::ParseSection(const std::vector& args,
                                 std::string* err) {
	// Leo, 参数小于3,service不合格,返回false
    if (args.size() < 3) {
        *err = "services must have a name and a program";
        return false;
    }
    // Leo, name为args[1],第二个参数,即zygote
    const std::string& name = args[1];
    // Leo, 名称是否合法
    if (!IsValidName(name)) {
        *err = StringPrintf("invalid service name '%s'", name.c_str());
        return false;
    }

    // Leo,设置args参数值
    std::vector str_args(args.begin() + 2, args.end());
    // Leo,创建service_对象
    service_ = std::make_unique(name, "default", str_args);
    return true;
}
此时,创建service_对象,看Service的构造函数

Service::Service(const std::string& name, const std::string& classname,
                 const std::vector& args)
    : name_(name), classname_(classname), flags_(0), pid_(0), time_started_(0),
      time_crashed_(0), nr_crashed_(0), uid_(0), gid_(0), seclabel_(""),
      ioprio_class_(IoSchedClass_NONE), ioprio_pri_(0), args_(args) {
    onrestart_.InitSingleTrigger("onrestart");
}
可以看到,此时将service_对象的name_参数默认设置为zygote,classname为android,args_为args参数,即后面四个参数,请注意此地关键字为onrestart

OK,init.zygote32.rc文件的第一行解析完成,接下来第二行

class main
由于关键字class,并不在service/on/import中,因此,走的是ParseConfigFile下面的else分支,因此调用的是ParseLineSection方法

service.cpp文件

bool ServiceParser::ParseLineSection(const std::vector& args,
                                     const std::string& filename, int line,
                                     std::string* err) const {
    return service_ ? service_->HandleLine(args, err) : false;
}
service_刚刚我们已经创建,因此其并不为空,因此走的是service->HandleLine方法

bool Service::HandleLine(const std::vector& args, std::string* err) {
    if (args.empty()) {
        *err = "option needed, but not provided";
        return false;
    }

    static const OptionHandlerMap handler_map;
    // Leo,查找需要调用的function
    auto handler = handler_map.FindFunction(args[0], args.size() - 1, err);

    // Leo,确认是否包含此方法
    if (!handler) {
        return false;
    }

    // Leo,直接调用该方法
    return (this->*handler)(args, err);
}
OptionHandlerMap是啥?

Service::OptionHandlerMap::Map& Service::OptionHandlerMap::map() const {
    constexpr std::size_t kMax = std::numeric_limits::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;
}
通过OptionHandlerMap,class关键字对应的是Service的HandleClass方法,因此,此时,HandleLine方法实际上是调用的HandleClass方法

bool Service::HandleClass(const std::vector& args, std::string* err) {
    classname_ = args[1];
    return true;
}
OK,设置此service_的classname为args[1],即main

依次类推,其他的行,分别调用的是对应的方法,对service_数据进行完善,需要注意的是onrestart关键字对应的service_

那么,解析init.rc文件,就到此结束,我们得到了一个Service的对象,service_,name为zygote,classname为main

那么,此zygote是如何来启动的呢?

2.启动所有restart标志的进程

在init.cpp文件中,做了两件事,第一就是解析init.rc文件,另一个就是启动所有restart标志的进程,那么

static void restart_processes()
{
    process_needs_restart = 0;
    ServiceManager::GetInstance().
        ForEachServiceWithFlags(SVC_RESTARTING, [] (Service* s) {
                s->RestartIfNeeded(process_needs_restart);
            });
}
调用了ServiceManager的ForEachServiceWithFlags方法,并且调用了Service对象s的RestrtIfNeeded方法

service.cpp文件

void ServiceManager::ForEachServiceWithFlags(unsigned matchflags,
                                             void (*func)(Service* svc)) const {
	// Leo,启动所有的services_
    for (const auto& s : services_) {
        if (s->flags() & matchflags) {
            func(s.get());
        }
    }
}
刚刚在第一步中,创建了一个service_,它的flags为0,此时必定会启动,因此,会调用该service_的RestartIfNeeded

void Service::RestartIfNeeded(time_t& process_needs_restart) {
    time_t next_start_time = time_started_ + 5;

    if (next_start_time <= gettime()) {
        flags_ &= (~SVC_RESTARTING);
        // Leo, 调用service_的Start方法
        Start();
        return;
    }

    if ((next_start_time < process_needs_restart) ||
        (process_needs_restart == 0)) {
        process_needs_restart = next_start_time;
    }
}
调用service_的Start方法

bool Service::Start() {
    ......
    // Leo, 创建一个子进程
    pid_t pid = fork();
    if (pid == 0) {
        umask(077);

        for (const auto& ei : envvars_) {
            add_environment(ei.name.c_str(), ei.value.c_str());
        }

        // Leo,创建socket连接
        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, s);
            }
        }

        ......

        // Leo,strs[0]为/system/bin/app_process,即启动/system/bin/app_process
        if (execve(strs[0], (char**) &strs[0], (char**) ENV) < 0) {
            ERROR("cannot execve('%s'): %s\n", strs[0], strerror(errno));
        }

        _exit(127);
    }

    if (pid < 0) {
        ERROR("failed to start '%s'\n", name_.c_str());
        pid_ = 0;
        return false;
    }

    // Leo,记录启动时间
    time_started_ = gettime();
    // Leo,设置进程的pid
    pid_ = pid;
    // Leo, 修改service_的flags值
    flags_ |= SVC_RUNNING;

    if ((flags_ & SVC_EXEC) != 0) {
        INFO("SVC_EXEC pid %d (uid %d gid %d+%zu context %s) started; waiting...\n",
             pid_, uid_, gid_, supp_gids_.size(),
             !seclabel_.empty() ? seclabel_.c_str() : "default");
    }

    NotifyStateChange("running");
    return true;
}
在Start方法中启动service_的socket,为其设定uid,pid,设置状态等

自此,天字第一号进程zygote启动

你可能感兴趣的:(Telephony分析)