Android zygote进程启动流程

news2024/11/24 1:55:58

zygote启动过程中涉及到以下模块:

  • app_process
  • zygote
    • USAP
    • socket
    • FileDescriptor (FD)
  • AndroidRuntime
  • AppRuntime (定义于app_process模块,继承自AndroidRuntime。)

init进程启动zygote进程:

#init.zygote32_64.rc
service zygote /system/bin/app_process32 -Xzygote /system/bin --zygote --start-system-server --socket-name=zygote
    class main
    priority -20
    user root
    group root readproc reserved_disk
    socket zygote stream 660 root system
    socket usap_pool_primary stream 660 root system
    onrestart exec_background - system system -- /system/bin/vdc volume abort_fuse
    onrestart write /sys/power/state on
    onrestart restart audioserver
    onrestart restart cameraserver
    onrestart restart media
    onrestart restart netd
    onrestart restart wificond
    writepid /dev/cpuset/foreground/tasks

service zygote_secondary /system/bin/app_process64 -Xzygote /system/bin --zygote --socket-name=zygote_secondary
    class main
    priority -20
    user root
    group root readproc reserved_disk
    socket zygote_secondary stream 660 root system
    socket usap_pool_secondary stream 660 root system
    onrestart restart zygote
    writepid /dev/cpuset/foreground/tasks

一、绑定socket

init.zygote32_64.rc脚本中分别定义了32位(primary)和64位(secondary)zygote进程的启动参数,在/dev/socket/下创建UNIX域的socket,并把socket的fd传给对应的进程。

在这里插入图片描述

“ANDROID_SOCKET_zygote”,"ANDROID_SOCKET_zygote_secondary"分别为两个zygote的socket在环境变量中对应的key值,通过key获取对应的value,创建FileDescriptor对象。通过 “ls -l /proc/${pid}/fd” 命令可查看对应进程的所有fd指向的符号链接。

    static LocalServerSocket createManagedSocketFromInitSocket(String socketName) {
        int fileDesc;
        final String fullSocketName = ANDROID_SOCKET_PREFIX + socketName;	// ANDROID_SOCKET_zygote

        try {
            String env = System.getenv(fullSocketName);
            fileDesc = Integer.parseInt(env);			// env="20"
        } catch (RuntimeException ex) {
            throw new RuntimeException("Socket unset or invalid: " + fullSocketName, ex);
        }

        try {
            FileDescriptor fd = new FileDescriptor();
            fd.setInt$(fileDesc);
            return new LocalServerSocket(fd);
        } catch (IOException ex) {
            throw new RuntimeException(
                "Error building socket from file descriptor: " + fileDesc, ex);
        }
    }

二、zygote启动

app_process进程:

//app_main.cpp
int main(int argc, char* const argv[])
{
  //...
    if (zygote) {
        runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
    } else if (className) {
        runtime.start("com.android.internal.os.RuntimeInit", args, zygote);
    } 
}

变量runtime是AppRuntime对象,调用AndoridRuntime对象start()方法:

//AndroidRuntime.cpp
/*
 * Start the Android runtime.  This involves starting the virtual machine
 * and calling the "static void main(String[] args)" method in the class
 * named by "className".
 *
 * Passes the main function two arguments, the class name and the specified
 * options string.
 */
void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
{
  //...
  
    /* start the virtual machine 
    * 1.启动Java虚拟机。
    */
    JniInvocation jni_invocation;
    jni_invocation.Init(NULL);
    JNIEnv* env;
    if (startVm(&mJavaVM, &env, zygote, primary_zygote) != 0) {
        return;
    }
    onVmCreated(env);
  
  	 /*
     * Register android functions.
     * 2.注册JNI方法。
     */
    if (startReg(env) < 0) {
        ALOGE("Unable to register all android natives\n");
        return;
    }
      
     /*
     * Start VM.  This thread becomes the main thread of the VM, and will
     * not return until the VM exits.
     * 3.启动对应类的静态 main()。
     */
    jmethodID startMeth = env->GetStaticMethodID(startClass, "main",
            "([Ljava/lang/String;)V");
    env->CallStaticVoidMethod(startClass, startMeth, strArray);
}

启动zygote时className变量是"com.android.internal.os.ZygoteInit",查看其main()方法:

//ZygoteInit.java
public static void main(String[] argv) {
  //...
  
  /*
  * 1. 执行预加载。
  */
  if (!enableLazyPreload) {
  	preload(bootTimingsTraceLog);
  }
  
  /*
  * 2. 实例化ZygoteServer()对象,
  *   1).初始化 Zygote server socket。
  *   2).初始化 USAP pool server socket。
  *   3).初始化 USAP pool event FD。
  */
  zygoteServer = new ZygoteServer(isPrimaryZygote);
  
  /*
  * 3. 启动 system_server进程,
  */
  if (startSystemServer) {
      Runnable r = forkSystemServer(abiList, zygoteSocketName, zygoteServer);

      // {@code r == null} in the parent (zygote) process, and {@code r != null} in the
      // child (system_server) process.
      if (r != null) {
           r.run();
           return;
      }
   }
  
  /*
  *	4. 循环接受处理 socket 事件。
  */
  // The select loop returns early in the child process after a fork and
  // loops forever in the zygote.
  caller = zygoteServer.runSelectLoop(abiList);
}

三、处理socket消息

ZygoteServer接收到socket消息后,调用processOneCommand方法解析消息参数。

//ZygoteServer.java
                            ZygoteConnection connection = peers.get(pollIndex);
                            final Runnable command = connection.processOneCommand(this);

最终在Zygote类的forkAndSpecialize方法中调用nativeForkAndSpecialize()方法fork新进程:

//Zygote.java
static int forkAndSpecialize(int uid, int gid, int[] gids, int runtimeFlags,
            int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose,
            int[] fdsToIgnore, boolean startChildZygote, String instructionSet, String appDataDir,
            boolean isTopApp, String[] pkgDataInfoList, String[] whitelistedDataInfoList,
            boolean bindMountAppDataDirs, boolean bindMountAppStorageDirs) {
        ZygoteHooks.preFork();
        int pid = nativeForkAndSpecialize(
                uid, gid, gids, runtimeFlags, rlimits, mountExternal, seInfo, niceName, fdsToClose,
                fdsToIgnore, startChildZygote, instructionSet, appDataDir, isTopApp,
                pkgDataInfoList, whitelistedDataInfoList, bindMountAppDataDirs,
                bindMountAppStorageDirs);
                ZygoteHooks.postForkCommon();
        return pid;
    }

重点查看ZygoteConnection类的processOneCommand()方法:

在nativeForkAndSpecialize()方法fork新进程后,通过判断返回的pid是否大于0区分母子进程。

​ fork是类Unix操作系统上创建进程的主要方法。fork用于创建子进程(等同于当前进程的副本),新的进程要通过老的进程复制自身得到,这就是fork!

​ fork作为一个函数被调用。这个函数会有两次返回,将子进程的PID返回给父进程,0返回给子进程。(如果小于0,则说明创建子进程失败)。

//ZygoteConnection.java
Runnable processOneCommand(ZygoteServer zygoteServer) {
    //...
    	pid = Zygote.forkAndSpecialize(parsedArgs.mUid, parsedArgs.mGid, parsedArgs.mGids,
                parsedArgs.mRuntimeFlags, rlimits, parsedArgs.mMountExternal, parsedArgs.mSeInfo,
                parsedArgs.mNiceName, fdsToClose, fdsToIgnore, parsedArgs.mStartChildZygote,
                parsedArgs.mInstructionSet, parsedArgs.mAppDataDir, parsedArgs.mIsTopApp,
                parsedArgs.mPkgDataInfoList, parsedArgs.mWhitelistedDataInfoList,
                parsedArgs.mBindMountAppDataDirs, parsedArgs.mBindMountAppStorageDirs);

        try {
            if (pid == 0) {
                // in child
                zygoteServer.setForkChild();

                zygoteServer.closeServerSocket();
                IoUtils.closeQuietly(serverPipeFd);
                serverPipeFd = null;

                return handleChildProc(parsedArgs, childPipeFd, parsedArgs.mStartChildZygote);
            } else {
                // In the parent. A pid < 0 indicates a failure and will be handled in
                // handleParentProc.
                IoUtils.closeQuietly(childPipeFd);
                childPipeFd = null;
                handleParentProc(pid, serverPipeFd);
                return null;
            }
        } finally {
            IoUtils.closeQuietly(childPipeFd);
            IoUtils.closeQuietly(serverPipeFd);
        }
}

所以可以看到handleChildProc()和handleParentProc()分别处理的是子进程,母进程的逻辑。

最终子进程执行zygoteInit()方法完成一个Android 应用程序的启动(初始化)

    public static final Runnable zygoteInit(int targetSdkVersion, long[] disabledCompatChanges,
            String[] argv, ClassLoader classLoader) {
        if (RuntimeInit.DEBUG) {
            Slog.d(RuntimeInit.TAG, "RuntimeInit: Starting application from zygote");
        }

        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ZygoteInit");
        RuntimeInit.redirectLogStreams();

        RuntimeInit.commonInit();
        ZygoteInit.nativeZygoteInit();
        return RuntimeInit.applicationInit(targetSdkVersion, disabledCompatChanges, argv,
                classLoader);
    }

ZygoteInit.nativeZygoteInit(); 使支持Binder进程间通信机制。

RuntimeInit.applicationInit(); 调用ActivityThread.main()方法,启动UI线程。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/374137.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【华为OD机试模拟题】用 C++ 实现 - 统计匹配的二元组个数(2023.Q1)

最近更新的博客 【华为OD机试模拟题】用 C++ 实现 - 去重求和(2023.Q1) 文章目录 最近更新的博客使用说明统计匹配的二元组个数题目输入输出描述示例一输入输出说明示例二输入输出说明备注Code使用说明 参加华为od机试,一定要注意不要完全背诵代码&

python读写hdfs文件的实用解决方案

大家好,我是爱编程的喵喵。双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。喜欢通过博客创作的方式对所学的知识进行总结与归纳,不仅形成深入且独到的理…

Python学习笔记之环境搭建

Python学习笔记之环境搭建1. 下载Python2. Windows 安装最新Python3. Linux 安装最新PythonPython是一种编程语言&#xff0c;可以让您更快地工作并更有效地集成系统。 您可以学习使用Python&#xff0c;并立即看到生产力的提高和维护成本的降低。 Python是荷兰程序员吉多范罗苏…

使用 OpenCV 进行面部和眼睛检测

OpenCV是构建计算机视觉应用程序的强大工具。计算机视觉中最常见的任务之一是人脸检测&#xff0c;它涉及识别图像或视频中人脸的存在、位置和面部特征。在本文中&#xff0c;我们将学习如何使用 Haar 级联分类器检测图像中的人脸。先决条件在开始之前&#xff0c;你需要在计算…

Android打造万能的BannerView无限轮播图

效果图&#xff1a;工程目录图&#xff1a;BannerAdapter&#xff1a;banner轮播图的适配器&#xff0c;因为服务器返回的列表图片的url&#xff0c;显示的时候需要转成IamgeViw&#xff1b; BannerScroller&#xff1a;设置切换页面的持续时间&#xff1b; BannerView&…

怎样划分MES系统实施阶段,三分钟告诉你整体实施思路

MES系统的实施阶段划分的思路是&#xff1a;在集成的前提下实现可视化&#xff0c;在可视化的基础上实现精细化&#xff0c;在精细化的前提下实现均衡化。生产过程透明的目的就是要实现生产过程的可视化&#xff0c;实现精细化生产。首先要做的就是收集生产信息&#xff0c;这是…

Linux->进程地址空间

目录 前言&#xff1a; 1. 程序地址空间回顾 2. 进程空间是什么 3. 进程地址空间与内存 4. 进程地址空间和内存的关联 5. 为什么要有进程地址空间 前言&#xff1a; 我们在平时学习的过程当中总是听到栈、堆、代码段等等储存空间&#xff0c;但是这些东西到底是什么&…

CSS3新特性

CSS3新特性 1.1、字体图标 何为字体图标&#xff1f; 字体图标展示的是图标&#xff0c;本质是字体。用于处理简单的、颜色单一的图片 字体图标的优点&#xff1a; 灵活性&#xff1a;灵活地修改样式&#xff0c;例如&#xff1a;尺寸、颜色等轻量级&#xff1a;体积小、渲…

Java并发编程(1)—— 操作系统、Linux、Java中进程与线程的区别

一、操作系统中什么是线程和进程 线程和进程都是操作系统中定义的结构&#xff0c;进程是系统中一个独立的活动程序&#xff0c;比如像QQ、网易云音乐&#xff0c;进程是操作系统进行资源分配的基本单位&#xff0c;一个进程中的所有线程共享进程内的资源&#xff0c;而线程则…

【Python学习笔记】第十八节 Python 内置函数

Python 内置函数内置函数就是Python给你提供的, 拿来直接用的函数&#xff0c;比如print&#xff0c;input等Python 内置函数一览表内置函数abs()divmod()input()open()staticmethod()all()enumerate()int()ord()str()any()eval()isinstance()pow()sum()basestring()execfile()…

ARMv8 同步和信号量(读写一致性问题):Load-Exclusive/Store-Exclusive指令详解

目录 一&#xff0c;Local Monitor 与 Global Monitor 1&#xff0c;Local Monitor 2&#xff0c;Global Monitor 二&#xff0c;Exclusive 指令的简单使用 三&#xff0c;Exclusive 示例程序 1&#xff0c;原子自加1程序 2&#xff0c;原子锁程序 四&#xff0c; 多处理…

算法设计与智能计算 || 专题一: 算法基础

专题一: 算法基础 文章目录专题一: 算法基础1. 算法的定义及特点1.1 算法的基本特征1.2 算法的基本要素1.3 算法的评定2 算法常见执行方法2.1 判断语句2.2 循环语句2.3 综合运用3. 计算复杂度4. 代码的重用5. 类函数的定义与使用5.1 定义类5.2 调用类函数1. 算法的定义及特点 …

_hand-2

实现一个迷你版的vue 入口 // js/vue.js class Vue {constructor (options) {// 1. 通过属性保存选项的数据this.$options options || {}this.$data options.data || {}this.$el typeof options.el string ? document.querySelector(options.el) : options.el// 2. 把da…

php mysql高校田径运动会成绩管理系统

第一章 引言 1 1.1 选题背景 1 1.2 编写目的 2 1.3 目标 2 1.4 功能需求 3 第二章 开发工具介绍 4 2.1 PHP 4 2.2 APACHE 5 2.3 MYSQL数据库 5 2.4 运行环境 WINDOWS XP 6 2.5 XAMPP 6 2.6 DREAMWEAVE8 6 2.7 EDITPLUS 7 第三章 需求…

【华为OD机试模拟题】用 C++ 实现 - 热点网络统计(2023.Q1)

最近更新的博客 【华为OD机试模拟题】用 C++ 实现 - 去重求和(2023.Q1) 文章目录 最近更新的博客使用说明热点网络统计【华为OD机试模拟题】题目输入输出描述示例一输入输出示例二输入输出Code使用说明 参加华为od机试,一定要注意不要完全背诵代码,需要理解之后模仿写出…

C++入门知识【超详解】

目录1.认识Chello worldC关键字2.命名空间3.std标准库4.输入输出5.缺省参数6.函数重载7.引用7.1引用的概念7.2引用的场景1.作参数2.作返回值7.3引用的注意点7.4指针和引用的区别8.auto关键字9.基于范围的for循环10.内联函数10.1概念10.2特征11. C98中的指针空值1.认识C hello …

数据结构——单链表(上)

&#x1f307;个人主页&#xff1a;_麦麦_ &#x1f4da;今日名言&#xff1a;“生活总是让我们遍体鳞伤&#xff0c;但到后来&#xff0c;那些受伤的地方一定会变成我们最强壮的地方。” ——海明威《永别了武器》 目录 ​编辑 一、前言 二、正言 3.1链表的概念及结构…

HMM(隐马尔科夫模型)-理论补充2

目录 一.大数定理 二.监督学习方法 1.初始概率 2.转移概率 3.观测概率 三.Baum-Welch算法 1.EM算法整体框架 2. Baum-Welch算法 3.EM过程 4.极大化 5.初始状态概率 6.转移概率和观测概率 四.预测算法 1.预测的近似算法 2.Viterbi算法 1.定义 2. 递推&#xff1…

倒计时2天:中国工程院院士谭建荣等嘉宾确认出席,“警务+”时代来临...

近日伴随公安部、科技部联合印发通知&#xff0c;部署推进科技兴警三年行动计划&#xff08;2023-2025年&#xff09;&#xff0c;现代科技手段与警务工作相结合的方式&#xff0c;正式被定义为未来警务发展的新趋势。 21世纪以来&#xff0c;随着科技的不断发展和创新&#xf…

硬间隔支持向量机算法、软间隔支持向量机算法、非线性支持向量机算法详细介绍及其原理详解

相关文章 K近邻算法和KD树详细介绍及其原理详解朴素贝叶斯算法和拉普拉斯平滑详细介绍及其原理详解决策树算法和CART决策树算法详细介绍及其原理详解线性回归算法和逻辑斯谛回归算法详细介绍及其原理详解硬间隔支持向量机算法、软间隔支持向量机算法、非线性支持向量机算法详细…