(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启动
- (N)Telephony分析(一)之zygote进程启动
- (N)Telephony分析(二)之SystemServer启动
- (N)Telephony分析(三)之PhoneApp启动
- (N)Telephony分析(四)之PhoneApp初始化分析
- Android Zygote系统进程启动过程分析(Android N)
- Android情景分析之详解init进程(以启动zygote为例)
- 二、Android情景分析之详解init进程(以启动zygote为例)
- (N)Telephony分析(五)之DcTracker的初始化
- (N)Telephony分析(七)之DataConnection建立
- SystemServer启动流程之Zygote启动(一)
- Android源码解析之(八)-->Zygote进程启动流程
- Android源码解析之(八)-->Zygote进程启动流程
- Android zygote与进程创建(一)
- Android zygote与进程创建(一)
- Telephony之进程与实体(原)
- (N)Telephony分析(六)之DcTracker的requestNetwork分析
- Android Telephony分析(一)--- Phone 详解
- Android系统进程Zygote启动过程的源代码分析(老罗的作品)
- VPN的安装配置
- 基本类型的转换如:int,double,long,string,Date,Calendar之间的转换
- 一些linux常用命令和功能
- POJ3422: Kaka's Matrix Travel 题解
- Windows技巧
- (N)Telephony分析(一)之zygote进程启动
- POJ 1847 Tram (简单最短路径dijkstra-floyd-spfa)
- java 策略模式 完全展现面向接口编程的经典样例
- A
- easyui树形菜单学习第一步
- 你有必要知道的 10 个 JavaScript 难点
- 获取一段时间的日期列表(查询日期列表、本月所有日期)
- DJI Lightbridge2接收端数据解析
- datatable warnning : table id=("xxxx")Ajax Error