目录

  • Android 源码学习 init启动
    • 从main.cpp开始
    • init.cpp 部分逻辑
    • init启动zygote
    • 属性服务
    • 总结

Android 源码学习 init启动

Android 11 init 启动流程学习。主要是学习刘望舒腾讯课堂教的AndroidFrameWork部分的笔记。
参考文章:
Android系统启动-Zygote进程
5张图搞懂Android系统启动的核心流程

从main.cpp开始

#mermaid-svg-mpSy48miYhftxM08 {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-mpSy48miYhftxM08 .error-icon{fill:#552222;}#mermaid-svg-mpSy48miYhftxM08 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-mpSy48miYhftxM08 .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-mpSy48miYhftxM08 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-mpSy48miYhftxM08 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-mpSy48miYhftxM08 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-mpSy48miYhftxM08 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-mpSy48miYhftxM08 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-mpSy48miYhftxM08 .marker.cross{stroke:#333333;}#mermaid-svg-mpSy48miYhftxM08 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-mpSy48miYhftxM08 .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-mpSy48miYhftxM08 text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-mpSy48miYhftxM08 .actor-line{stroke:grey;}#mermaid-svg-mpSy48miYhftxM08 .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-mpSy48miYhftxM08 .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-mpSy48miYhftxM08 #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-mpSy48miYhftxM08 .sequenceNumber{fill:white;}#mermaid-svg-mpSy48miYhftxM08 #sequencenumber{fill:#333;}#mermaid-svg-mpSy48miYhftxM08 #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-mpSy48miYhftxM08 .messageText{fill:#333;stroke:#333;}#mermaid-svg-mpSy48miYhftxM08 .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-mpSy48miYhftxM08 .labelText,#mermaid-svg-mpSy48miYhftxM08 .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-mpSy48miYhftxM08 .loopText,#mermaid-svg-mpSy48miYhftxM08 .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-mpSy48miYhftxM08 .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-mpSy48miYhftxM08 .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-mpSy48miYhftxM08 .noteText,#mermaid-svg-mpSy48miYhftxM08 .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-mpSy48miYhftxM08 .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-mpSy48miYhftxM08 .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-mpSy48miYhftxM08 .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-mpSy48miYhftxM08 .actorPopupMenu{position:absolute;}#mermaid-svg-mpSy48miYhftxM08 .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-mpSy48miYhftxM08 .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-mpSy48miYhftxM08 .actor-man circle,#mermaid-svg-mpSy48miYhftxM08 line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-mpSy48miYhftxM08 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} main.cpp first_stage_init.cpp seliunx.cpp init.cpp FirstStageMain "selinux_setup" "selinux_setup" "second_stage" "second_stage" 1.系统属性初始化 2.加载默认的系统属性 3.启动属性服务 4.解析 init.rc main.cpp first_stage_init.cpp seliunx.cpp init.cpp

system/core/init/main.cpp

using namespace android::init;int main(int argc, char** argv) {#if __has_feature(address_sanitizer)__asan_set_error_report_callback(AsanReportCallback);
#endifif (!strcmp(basename(argv[0]), "ueventd")) {return ueventd_main(argc, argv);}if (argc > 1) {if (!strcmp(argv[1], "subcontext")) {android::base::InitLogging(argv, &android::base::KernelLogger);const BuiltinFunctionMap& function_map = GetBuiltinFunctionMap();return SubcontextMain(argc, argv, &function_map);}// 第二次调用if (!strcmp(argv[1], "selinux_setup")) {return SetupSelinux(argv);}// 第三次调用if (!strcmp(argv[1], "second_stage")) {return SecondStageMain(argc, argv);}}// 第一次调用return FirstStageMain(argc, argv);
}

init.cpp 部分逻辑

system/core/init/init.cpp

int SecondStageMain(int argc, char** argv) {...// 系统属性初始化PropertyInit();...// 创建epoll,epoll是Linux内核的可扩展I/O事件通知机制Epoll epoll;if(auto result = epol.Open();!result.ok()){PLOG(FATAL) << result.error();}// 注册信号处理InstallSignalFdHandler(&epoll);//加载默认的系统属性InstallInitNotifier(&epoll);//启动属性服务StartPropertyService(&property_fd);...ActionManager& am = ActionManager::GetInstance();ServiceList& sm = ServiceList::GetInstance();//解析init.rcLoadBootScripts(am,sm);...return 0;
}
 static void LoadBootScripts(ActionManager& action_manager, ServiceList& service_list) {Parser parser = CreateParser(action_manager, service_list);std::string bootscript = GetProperty("ro.boot.init_rc", "");if (bootscript.empty()) {parser.ParseConfig("/system/etc/init/hw/init.rc");if (!parser.ParseConfig("/system/etc/init")) {late_import_paths.emplace_back("/system/etc/init");}parser.ParseConfig("/system_ext/etc/init")if (!parser.ParseConfig("/product/etc/init")) {late_import_paths.emplace_back("/product/etc/init");}if (!parser.ParseConfig("/odm/etc/init")) {late_import_paths.emplace_back("/odm/etc/init");}if (!parser.ParseConfig("/vendor/etc/init")) {late_import_paths.emplace_back("/vendor/etc/init");}} else {parser.ParseConfig(bootscript);}
}

init启动zygote

/system/core/rootdir/init.zygote64.rc

service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-serverclass mainpriority -20user rootgroup root readproc reserved_disksocket zygote stream 660 root systemsocket usap_pool_primary stream 660 root systemonrestart exec_background - system system -- /system/bin/vdc volume abort_fuseonrestart write /sys/power/state ononrestart restart audioserveronrestart restart cameraserveronrestart restart mediaonrestart restart netdonrestart restart wificondwritepid /dev/cpuset/foreground/tasks

init.rc中还import了其他的rc文件,解析完init.rc后,依次解析其他的rc文件

import /system/etc/init/hw/init.${ro.zygote}.rc

nonencrypted 会触发启动main类别的服务。
main 指zygote
/system/core/rootdir/init.rc 部分代码

on nonencryptedclass_start mainclass_start late_start

class_start 在/system/core/init/builtins.cpp 文件中定义
builtins.cpp

static Result<void> do_class_start(const BuiltinArguments& args) {// Do not start a class if it has a property persist.dont_start_class.CLASS set to 1.if (android::base::GetBoolProperty("persist.init.dont_start_class." + args[1], false))return {};// Starting a class does not start services which are explicitly disabled.// They must  be started individually.for (const auto& service : ServiceList::GetInstance()) {if (service->classnames().count(args[1])) {if (auto result = service->StartIfNotDisabled(); !result.ok()) {LOG(ERROR) << "Could not start service '" << service->name()<< "' as part of class '" << args[1] << "': " << result.error();}}}return {};
}

/system/core/init/service.cpp

Result<void> Service::StartIfNotDisabled() {if (!(flags_ & SVC_DISABLED)) {return Start();} else {flags_ |= SVC_DISABLED_START;}return {};
}Result<void> Service::Start() {...pid_t pid = -1;if (namespace_flags_) {pid = clone(nullptr, nullptr, namespace_flags_ | SIGCHLD, nullptr);} else {pid = fork();}if (pid == 0) {...if(!ExpandArgsAndExecv(args_, sigstop_)){PLOG(ERROR) << "cannot execve('" << args_[0]<< "').See the 'Debugging init' section of init's README.md for tips";}_exit(127);}if (pid < 0) {pid_ = 0;return ErrnoError() << "Failed to fork";}...return {};
}

service 就是 zygote
ExpandArgsAndExecv 传递的参数就是“/system/bin/app_process64”

static bool ExpandArgsAndExecv(const std::vector<std::string>& args, bool sigstop) {std::vector<std::string> expanded_args;std::vector<char*> c_strings;expanded_args.resize(args.size());c_strings.push_back(const_cast<char*>(args[0].data()));for (std::size_t i = 1; i < args.size(); ++i) {auto expanded_arg = ExpandProps(args[i]);if (!expanded_arg.ok()) {LOG(FATAL) << args[0] << ": cannot expand arguments': " << expanded_arg.error();}expanded_args[i] = *expanded_arg;c_strings.push_back(expanded_args[i].data());}c_strings.push_back(nullptr);if (sigstop) {kill(getpid(), SIGSTOP);}return execv(c_strings[0], c_strings.data()) == 0;
}

其中/system/bin/app_process64的映射的执行文件为:/frameworks/base/cmds/app_process/app_main.cpp,定义在
/frameworks/base/cmds/app_process/Android.bp
低版本是
/frameworks/base/cmds/app_process/Android.mk

cc_binary {name: "app_process",srcs: ["app_main.cpp"],multilib: {lib32: {version_script: ":art_sigchain_version_script32.txt",suffix: "32",},lib64: {version_script: ":art_sigchain_version_script64.txt",suffix: "64",},},ldflags: ["-Wl,--export-dynamic"],shared_libs: ["libandroid_runtime","libbinder","libcutils","libdl","libhidlbase","liblog","libnativeloader","libutils",// This is a list of libraries that need to be included in order to avoid// bad apps. This prevents a library from having a mismatch when resolving// new/delete from an app shared library.// See b/21032018 for more details."libwilhelm",],whole_static_libs: ["libsigchain"],compile_multilib: "both",cflags: ["-Wall","-Werror","-Wunused","-Wunreachable-code",],// If SANITIZE_LITE is revived this will need://product_variables: {//    sanitize_lite: {//        // In SANITIZE_LITE mode, we create the sanitized binary in a separate location (but reuse//        // the same module). Using the same module also works around an issue with make: binaries//        // that depend on sanitized libraries will be relinked, even if they set LOCAL_SANITIZE := never.//        ////        // Also pull in the asanwrapper helper.//        relative_install_path: "asan",//        required: ["asanwrapper"],//    },//},// Create a symlink from app_process to app_process32 or 64// depending on the target configuration.symlink_preferred_arch: true,
}

/frameworks/base/cmds/app_process/app_main.cpp

int main(int argc, char* const argv[]){......if (zygote) {// 启动zygoteruntime.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.");}
}

属性服务

void StartPropertyService(int* epoll_socket) {InitPropertySet("ro.property_service.version", "2");int sockets[2];if (socketpair(AF_UNIX, SOCK_SEQPACKET | SOCK_CLOEXEC, 0, sockets) != 0) {PLOG(FATAL) << "Failed to socketpair() between property_service and init";}*epoll_socket = from_init_socket = sockets[0];init_socket = sockets[1];StartSendingMessages();if (auto result = CreateSocket(PROP_SERVICE_NAME, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK,false, 0666, 0, 0, {});result.ok()) {property_set_fd = *result;} else {LOG(FATAL) << "start_property_service socket creation failed: " << result.error();}// 监听socket 属性服务,最多同时被8个视图使用listen(property_set_fd, 8);// 创建属性服务线程auto new_thread = std::thread{PropertyServiceThread};property_service_thread.swap(new_thread);
}static void PropertyServiceThread() {Epoll epoll;if (auto result = epoll.Open(); !result.ok()) {LOG(FATAL) << result.error();}// 监听property_set_fd,当socket有请求的时候调用handle_property_set_fd 来处理if (auto result = epoll.RegisterHandler(property_set_fd, handle_property_set_fd);!result.ok()) {LOG(FATAL) << result.error();}if (auto result = epoll.RegisterHandler(init_socket, HandleInitSocket); !result.ok()) {LOG(FATAL) << result.error();}while (true) {auto pending_functions = epoll.Wait(std::nullopt);if (!pending_functions.ok()) {LOG(ERROR) << pending_functions.error();} else {for (const auto& function : *pending_functions) {(*function)();}}}
}static void handle_property_set_fd() {.....switch (cmd) {case PROP_MSG_SETPROP:{......break;}case PROP_MSG_SETPROP2:{......// 关键代码uint32_t result = HandlePropertySet(name, value, source_context, cr, &socket, &error);if (result != PROP_SUCCESS) {LOG(ERROR) << "Unable to set property '" << name << "' from uid:" << cr.uid<< " gid:" << cr.gid << " pid:" << cr.pid << ": " << error;}socket.SendUint32(result);break;}}
}uint32_t HandlePropertySet(const std::string& name, const std::string& value,const std::string& source_context, const ucred& cr,SocketConnection* socket, std::string* error) {.......// 设置属性return PropertySet(name, value, error);
}static uint32_t PropertySet(const std::string& name, const std::string& value, std::string* error) {size_t valuelen = value.size();if (!IsLegalPropertyName(name)) {*error = "Illegal property name";return PROP_ERROR_INVALID_NAME;}if (auto result = IsLegalPropertyValue(name, value); !result.ok()) {*error = result.error().message();return PROP_ERROR_INVALID_VALUE;}// 从属性存储空间查找属性prop_info* pi = (prop_info*) __system_property_find(name.c_str());if (pi != nullptr) {// ro.* properties are actually "write-once".// ro开头的是只读,只能设置一次if (StartsWith(name, "ro.")) {*error = "Read-only property was already set";return PROP_ERROR_READ_ONLY_PROPERTY;}__system_property_update(pi, value.c_str(), valuelen);} else {int rc = __system_property_add(name.c_str(), name.size(), value.c_str(), valuelen);if (rc < 0) {*error = "__system_property_add failed";return PROP_ERROR_SET_FAILED;}}// Don't write properties to disk until after we have read all default// properties to prevent them from being overwritten by default values.if (persistent_properties_loaded && StartsWith(name, "persist.")) {WritePersistentProperty(name, value);}// If init hasn't started its main loop, then it won't be handling property changed messages// anyway, so there's no need to try to send them.auto lock = std::lock_guard{accept_messages_lock};if (accept_messages) {PropertyChanged(name, value);}return PROP_SUCCESS;
}

总结

init进程在启动过程中主要做了三件事:

  1. 创建一些文件并挂载设备
  2. 启动属性服务
  3. 解析init.rc配置文件并启动zygote进程

【Android 源码学习】 init启动相关推荐

  1. android源码学习- APP启动流程(android12源码)

    前言: 百度一搜能找到很多讲APP启动流程的,但是往往要么就是太老旧(还是基于android6去分析的),要么就是不全(往往只讲了整个流程的一小部分).所以我结合网上现有的文章,以及源码的阅读和调试, ...

  2. 【Android 源码学习】Zygote启动原理

    Android 源码学习 Zygote启动原理 望舒课堂 Zygote进程启动原理学习记录整理. Zygote简介 Zygote是进程在init进程启动时创建的,进程本身是app_process,来源 ...

  3. 【Android 源码学习】SystemServer启动原理

    Android 源码学习 SystemServer启动原理 望舒课堂 SystemServer进程启动原理学习记录整理. 参考文章: Android系统启动流程(三)解析SyetemServer进程启 ...

  4. 【Android 源码学习】系统架构和启动流程

    Android 源码学习 系统架构和启动流程 望舒课堂 学习记录整理.以及以下参考文章的整理汇总.便于我个人的学习记录. 感谢IngresGe,Gityuan的精彩文章.为我们这些初探android系 ...

  5. Android源码学习之浅析SystemServer脉络

    在之前的博文中<Android源码学习之如何创建使用JNI>和<Android源码学习之如何使用eclipse+NDK>中,浅谈了如何创建使用JNI和如何利用NDK工具开发创建 ...

  6. Android源码阅读---init进程

    Android源码阅读-init进程 文章目录 Android源码阅读---init进程 1. 编译命令和进程入口 1. init 进程编译命令 2. main函数流程 2. 主函数处理流程 1. 创 ...

  7. Android源码编译及启动模拟器

    Android源码编译及启动模拟器 源码下载 (1)更改下载源 (2)安装源码下载工具 (3)下载源码 (4)安装环境依赖 源码编译 启动模拟器 源码下载 Ubuntu18.0 (1)更改下载源 源码 ...

  8. android源码学习-Toast实现原理讲解

    前言: 前些日志QQ群有朋友发了一个Toast的崩溃日志.Toast如此简单的用法怎么会崩溃呢?所以顺便就学习了一下Toast在源码中的实现,不算复杂,但内容挺多的,这里就来分享一下,方便读者. 一. ...

  9. 【Android 源码学习】SharedPreferences 源码学习

    第一章:SharedPreferences 源码学习 文章目录 第一章:SharedPreferences 源码学习 Android SharedPreferences的缺陷 MMKV.Jetpack ...

最新文章

  1. 真正理解线程上下文类加载器(多案例分析)
  2. sp_MSforeachtable使用方法
  3. 在fedora21 上的php+mysql+apache环境搭建
  4. SpringBoot+Shiro学习(一):主要模块介绍
  5. 页面中文显示问题之终结
  6. BZOJ 1012: [JSOI2008]最大数maxnumber(线段树)
  7. 安卓开发.四大组件.activity.1
  8. 推荐两款 GTD 工具
  9. java作业 景区门票
  10. android中的websocket 应用
  11. STM32 RCC时钟配置
  12. Datawhale 零基础入门CV赛事-Task2 数据读取与数据扩增
  13. 中专计算机应用专业简历模板,2016计算机应用专业个人简历模板
  14. 计算机黑屏的原因及修复,导致笔记本电脑开机黑屏的原因以及对应的修复方法...
  15. python 读写三菱PLC数据,使用以太网读写Q系列,L系列,Fx系列的PLC数据
  16. SECRET文件保险柜 V2.7 --统一管理并加密文件
  17. linux删除某条历史命令,如何从Linux/Unix Bash shell上删除历史记录中的一条命令?...
  18. linux 下的无线网络配置,详解在LINUX环境下怎样设置无线网络配置
  19. ie10服务器运行失败,win7系统下无法安装ie10浏览器如何解决?win7系统下无法安装ie10浏览器三种解决方法...
  20. 公司法人代表变更需要多少钱?

热门文章

  1. 电子书籍下載點 E-Book
  2. 云原生负载均衡器之 OpenELB 中文使用指南
  3. 德国品牌超大功率大扭力无抖动断刀技术雕刻机主轴
  4. 今年第一季度中国智能手机市场:OPPO排名榜首
  5. Spring MVC_5
  6. vue-element-admin(后端管理系统)
  7. 宝能系全面接管南玻 监管部门连发关注函
  8. 瑞吉外卖项目——订单明细分页查询
  9. 1Z206010、建设工程施工招标与投标
  10. iText5使用绝对定位制作pdf打印针式发票,支持跳页