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

来源:互联网 发布:超级捕快软件 编辑:程序博客网 时间:2024/05/22 15:18

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<ServiceParser>());    parser.AddSectionParser("on", std::make_unique<ActionParser>());    parser.AddSectionParser("import", std::make_unique<ImportParser>());    // 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<SectionParser> 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<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 (;;) {        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<std::string>& 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<std::string>& 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<std::string> str_args(args.begin() + 2, args.end());    // Leo,创建service_对象    service_ = std::make_unique<Service>(name, "default", str_args);    return true;}
此时,创建service_对象,看Service的构造函数

Service::Service(const std::string& name, const std::string& classname,                 const std::vector<std::string>& 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<std::string>& 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<std::string>& 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<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;}
通过OptionHandlerMap,class关键字对应的是Service的HandleClass方法,因此,此时,HandleLine方法实际上是调用的HandleClass方法

bool Service::HandleClass(const std::vector<std::string>& 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启动

阅读全文
0 0
原创粉丝点击