Android Framework分析(3)——Zygote进程源码分析

2022-06-23 14:11:13 浏览数 (1)

Zygote进程源码分析

由app_process运行ZygoteInit class

zygote由java编写而成,不能直接由init进程启动运行。若想执行zygote类,必须先创建虚拟机,然后在虚拟机上运行ZygoteInit类。执行这一任务的就是app_process程序。 下面我们开始分析zygote进程的启动流程: /system/core/rootdir/init.rc

可以看到init.rc中有如下导包

代码语言:javascript复制
import /init.$(ro.zygote).rc

如果是64位系统,$(ro.zygote)的值为"zygote64" /system/core/rootdir/init.zygote64.rc

代码语言:javascript复制
service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server
    class main
    priority -20
    user root
    group root readproc reserved_disk
    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
    onrestart restart wificond
    writepid /dev/cpuset/foreground/tasks

app_process64程序的main函数入口如下: frameworks/base/cmds/app_process/app_main.cpp

代码语言:javascript复制
int main(int argc, char* const argv[])
{
    ......
    AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
    ......
    // Parse runtime arguments.  Stop at first unrecognized option.
    bool zygote = false;
    bool startSystemServer = false;
    ......

    while (i < argc) {
        const char* arg = argv[i  ];
        if (strcmp(arg, "--zygote") == 0) {
            zygote = true;
        } else if (strcmp(arg, "--start-system-server") == 0) {
            startSystemServer = true;
        } 
        ......
    }

    ......
    if (zygote) {
        //zygote进程
        runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
    } else if (className) {
        //普通java进程
        runtime.start("com.android.internal.os.RuntimeInit", args, zygote);
    }
}

如果是zygote进程就走ZygoteInit代码,如果是普通java进程就走RuntimeInit代码,例如常用的am命令,/system/bin/am实际上是一个shell脚本,查看里面的代码可知是通过app_process来启动普通java进程,然后和AMS进行通信。

这里AppRuntime继承自AndroidRuntime,所以看到AndroidRuntime的start方法

frameworks/base/core/jni/AndroidRuntime.cpp

代码语言:javascript复制
//AppRuntime继承自AndroidRuntime
void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
{
    /* start the virtual machine */
    JniInvocation jni_invocation;
    // ① 加载指定的虚拟机的库(art或者dalvik)
    jni_invocation.Init(NULL); 
    JNIEnv* env;
    // ② 创建java虚拟机
    if (startVm(&mJavaVM, &env, zygote) != 0) {
        return;
    }

    // ③ 注册JNI函数
    if (startReg(env) < 0) {
        return;
    }

    ......
    // ④ 正式进入java的世界,调用ZygoteInit.java的main方法
    jclass startClass = env->FindClass(slashClassName);
    ......
    jmethodID startMeth = env->GetStaticMethodID(startClass, "main","([Ljava/lang/String;)V");
    ......
    env->CallStaticVoidMethod(startClass, startMeth, strArray);
    ......
}

①: 加载虚拟机的库(art或者dalvik),并且函数指针指向库对应的函数(如:JNI_CreateJavaVM函数) libnativehelper/JniInvocation.cpp

代码语言:javascript复制
bool JniInvocation::Init(const char* library) {
  //获取要加载库的名称
  library = GetLibrary(library, buffer);

  //动态加载对应的虚拟机库
  handle_ = dlopen(library, RTLD_NOW);
  ......
  //JNI_CreateJavaVM_函数指针指向虚拟机库中的JNI_CreateJavaVM函数
  if (!FindSymbol(reinterpret_cast<void**>(&JNI_CreateJavaVM_),
                  "JNI_CreateJavaVM")) {
    return false;
  }
  .......
  return true;
}

GetLibraray()函数获取动态库的名称(libart.so或者libdalvik .so),dlopen()函数动态加载虚拟机库,RTLD_NOW表示返回之前立即链接所有未定位的符号,FindSysmbol()函数指针指向对应的函数。

函数说明: dlopen以指定模式打开指定的动态连接库文件,并返回一个句柄给调用进程,dlerror返回出现的错误,dlsym通过句柄和连接符名称获取函数名或者变量名,dlclose来卸载打开的库。 dlopen打开模式如下:

RTLD_LAZY 暂缓决定,等有需要时再解出符号 RTLD_NOW 立即决定,返回前解除所有未决定的符号。

dlclose(handle);关闭动态链接库

代码语言:javascript复制
bool JniInvocation::FindSymbol(void** pointer, const char* symbol) {
  *pointer = dlsym(handle_, symbol);
  if (*pointer == NULL) {
    ALOGE("Failed to find symbol %s: %sn", symbol, dlerror());
    dlclose(handle_);
    handle_ = NULL;
    return false;
  }
  return true;
}

libnativehelper/JniInvocation.cpp

代码语言:javascript复制
static const char* kLibrarySystemProperty = "persist.sys.dalvik.vm.lib.2";
static const char* kDebuggableSystemProperty = "ro.debuggable";
static const char* kDebuggableFallback = "0";  // Not debuggable.
static const char* kLibraryFallback = "libart.so";

const char* JniInvocation::GetLibrary(const char* library, char* buffer, bool (*is_debuggable)(),
                                      int (*get_library_system_property)(char* buffer)) {
#ifdef __ANDROID__
  const char* default_library;
  //如果不是debug设备,library的值为"libart.so"
  if (!is_debuggable()) {
    // Not a debuggable build.
    // Do not allow arbitrary library. Ignore the library parameter. This
    // will also ignore the default library, but initialize to fallback
    // for cleanliness.
    library = kLibraryFallback;
    default_library = kLibraryFallback;
  } else {
    // Debuggable build.
    // Accept the library parameter. For the case it is NULL, load the default
    // library from the system property.
    if (buffer != NULL) {
      if (get_library_system_property(buffer) > 0) {
        default_library = buffer;
      } else {
        default_library = kLibraryFallback;
      }
    } else {
      // No buffer given, just use default fallback.
      default_library = kLibraryFallback;
    }
  }
#else
  UNUSED(buffer);
  UNUSED(is_debuggable);
  UNUSED(get_library_system_property);
  const char* default_library = kLibraryFallback;
#endif
  if (library == NULL) {
    library = default_library;
  }

  return library;
}
代码语言:javascript复制
bool IsDebuggable() {
#ifdef __ANDROID__
  char debuggable[PROP_VALUE_MAX] = {0};
  __system_property_get("ro.debuggable", debuggable);
  return strcmp(debuggable, "1") == 0;
#else
  return false;
#endif
}

②: 创建java虚拟机 frameworks/base/core/jni/AndroidRuntime.cpp

代码语言:javascript复制
int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv, bool zygote)
{
    JavaVMInitArgs initArgs;
    ......
    initArgs.version = JNI_VERSION_1_4;
    initArgs.options = mOptions.editArray();
    initArgs.nOptions = mOptions.size();
    initArgs.ignoreUnrecognized = JNI_FALSE;

    ......
    //创建java虚拟机
    if (JNI_CreateJavaVM(pJavaVM, pEnv, &initArgs) < 0) {
        ALOGE("JNI_CreateJavaVM failedn");
        return -1;
    }

    return 0;
}

JNI_CreateJavaVM()是JniInvocation.cpp中的函数,会调用到①中所说的JNI_CreateJavaVM_()函数指针,最后调用到相应虚拟机动态库中的JNI_CreateJavaVM()函数,创建对应的虚拟机。initArgs表示传入的虚拟机参数。

代码语言:javascript复制
C/C  预处理指令,常见的预处理指令如下:

#空指令,无任何效果
#include包含一个源代码文件
#define定义宏
#undef取消已定义的宏
#if如果给定条件为真,则编译下面代码
#ifdef如果宏已经定义,则编译下面代码
#ifndef如果宏没有定义,则编译下面代码
#elif如果前面的#if给定条件不为真,当前条件为真,则编译下面代码
#endif结束一个#if……#else条件编译块
#error停止编译并显示错误信息

③: 注册JNI本地函数 我们先来熟悉一下几个数据结构: frameworks/base/core/jni/AndroidRuntime.cpp

代码语言:javascript复制
#define REG_JNI(name)     { name }

struct RegJNIRec {
    int (*mProc)(JNIEnv*);
};
......
static const RegJNIRec gRegJNI[] = {
    REG_JNI(register_com_android_internal_os_RuntimeInit),
    REG_JNI(register_com_android_internal_os_ZygoteInit_nativeZygoteInit),
    REG_JNI(register_android_os_SystemClock),
    REG_JNI(register_android_util_EventLog),
    REG_JNI(register_android_util_Log),
    ......
};

gRegJNI是RegJNIRec结构体数组,然后数组通过REG_JNI宏定义初始化。例如gRegJNI第一个元素的初始化,等同于:

代码语言:javascript复制
gRegJNI[0] = {register_com_android_internal_os_RuntimeInit};

那么gRegJNI[0]中RegJNIRec结构体的mProc函数指针就指向上面的函数register_com_android_internal_os_RuntimeInit,数组中的其它元素也同理。下面我们继续分析JNI本地函数的注册。

frameworks/base/core/jni/AndroidRuntime.cpp

代码语言:javascript复制
int AndroidRuntime::startReg(JNIEnv* env)
{
    ......
    //注册JNI本地函数,将gRegJNI数组传入
    if (register_jni_procs(gRegJNI, NELEM(gRegJNI), env) < 0) {
        return -1;
    }
    ......
    return 0;
}

static int register_jni_procs(const RegJNIRec array[], size_t count, JNIEnv* env)
{
    //遍历执行gRegJNI数组中元素的mProc函数
    //(mProc是函数指针,数组初始化的时候已经指向指定的函数)
    for (size_t i = 0; i < count; i  ) {
        if (array[i].mProc(env) < 0) {
            return -1;
        }
    }
    return 0;
}

startReg会调用register_jni_procs遍历调用gRegJNI数组中的mProc函数,以第一个元素为例,gRegJNI[0].mProc(env)由上面的分析可知调用的实际是register_com_android_internal_os_RuntimeInit(env)函数。

frameworks/base/core/jni/AndroidRuntime.cpp

代码语言:javascript复制
int register_com_android_internal_os_RuntimeInit(JNIEnv* env)
{
    const JNINativeMethod methods[] = {
        { "nativeFinishInit", "()V",
            (void*) com_android_internal_os_RuntimeInit_nativeFinishInit },
        ......
    };
    //最后会调用到(*env)->RegisterNative()注册
    return jniRegisterNativeMethods(env, "com/android/internal/os/RuntimeInit",
        methods, NELEM(methods));
}

用上面的代码可知,nativeFinishInit函数映射了com_android_internal_os_RuntimeInit_nativeFinishInit函数,当java调用nativeFinishInit函数时,实际会调用到c/c 中的com_android_internal_os_RuntimeInit_nativeFinishInit函数。有读者可能会问,java调用jni函数时,虚拟机会自动映射,为什么要自己映射呢?如果jni函数比较少,这么做确实可行,但是我们可以看到gRegJNI数组是很庞大的,需要映射的函数也很多,如果全部交给虚拟机映射,会大大降低虚拟机的执行性能,所以我们提前注册JNI函数,虚拟机就可以直接找到对应的函数进行调用。

④: 通过反射调用ZygoteInit.java的main函数,正式进入java的世界。env->FindClass获取ZygoteInit类的类型,env->GetStaticMethodID获取函数main的函数id,env->CallStaticVoidMethod调用ZygoteInit.java的静态函数main。

ZygoteInit类的功能

至此,我们已经创建好了虚拟机,并且将ZygoteInit类装载到了虚拟机。接下来,ZygoteInit类将会被运行,那么ZygoteInit类具体有哪些功能呢?大致概括为如下几点:

代码语言:javascript复制
绑定套接字,用来接收新Android应用程序运行请求
预加载Android Application Framework 使用的类与资源
启动并运行SystemServer
处理新Android应用程序运行请求

ZygoteInit的main函数: frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

代码语言:javascript复制
public static void main(String argv[]) {
    ZygoteServer zygoteServer = new ZygoteServer();
    ......
    try{
        boolean startSystemServer = false;
        String socketName = "zygote";//套接字默认名称zygote
        for (int i = 1; i < argv.length; i  ) {
            if ("start-system-server".equals(argv[i])) {
                startSystemServer = true;
           }
            ......
        }

        // ① 绑定/dev/socket/zygote套接字,用来接收Android应用程序运行请求
        zygoteServer.registerServerSocketFromEnv(socketName);
        ......
          
        if (!enableLazyPreload) {
            ......
            // ② 预加载类与资源
            preload(bootTimingsTraceLog);
            ......
        }

        ......
        if (startSystemServer) {
            // ③ fork出system_server子进程
           Runnable r = forkSystemServer(abiList, socketName, zygoteServer);

            // ③ {@code r == null}表示是父进程(zygote),{@code r != null}在子进程(system_server)
            if (r != null) {
                // ③ 如果是子进程(system_server)就执行run()方法,并返回,父进程(zygote)就继续往下执行
                r.run();
                return;
            }
        }

        Log.i(TAG, "Accepting command socket connections");

        // ④ 这轮询会在zygote进程中无限循环,而fork出的子进程(Android应用进程)会退出来
        caller = zygoteServer.runSelectLoop(abiList);
    } catch (Throwable ex) {
        Log.e(TAG, "System zygote died with exception", ex);
        throw ex;
    } finally {
        //system_server进程和android应用进程会关闭socket,zygote仍然在runSelectLoop中轮询监听socket
        zygoteServer.closeServerSocket();
    }
    

    // ④ Android应用进程会走到这儿,执行相应的命令
    if (caller != null) {
        caller.run();
    }
}

①: 绑定套接字,用来接收运行Android应用运行请求 frameworks/base/core/java/com/android/internal/os/ZygoteServer.java

代码语言:javascript复制
void registerServerSocketFromEnv(String socketName) {
    if (mServerSocket == null) {
        int fileDesc;
        //fullSocketName为“ANDROID_SOCKET_zygote”
        final String fullSocketName = ANDROID_SOCKET_PREFIX   socketName;
        try {
            //获取ANDROID_SOCKET_zygote的坏境变量(即为/dev/socket/zygote的文件描述符的值)
            //是init进程在启动zygote进程时保存到环境变量中的
            String env = System.getenv(fullSocketName);
            fileDesc = Integer.parseInt(env);
        } catch (RuntimeException ex) {
            throw new RuntimeException(fullSocketName   " unset or invalid", ex);
        }
        
        try {
            //绑定socket,在后面用来接收Android应用启动请求
            FileDescriptor fd = new FileDescriptor();
            fd.setInt$(fileDesc);
            mServerSocket = new LocalServerSocket(fd);
            mCloseSocketFd = true;
        } catch (IOException ex) {
            ......
        }
    }
}

②: 预加载类和资源,后面从zygote进程fork出的应用进程可以直接共享,加快应用进程启动速度。 frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

代码语言:javascript复制
static void preload(TimingsTraceLog bootTimingsTraceLog) {
    ......
    preloadClasses();
    ......
    preloadResources();
    ......
    nativePreloadAppProcessHALs();
    ......
    preloadOpenGL();
    preloadSharedLibraries();
    preloadTextResources();
    .......
    }

③: forkSystemServer fork出system_server子进程,并返回可以调用SystemServer中main方法的Runnable r,并执行对应的run方法,而父进程zygote则继续往下执行runSelectLoop,监听Android应用运行执行请求。

frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

代码语言:javascript复制
private static Runnable forkSystemServer(String abiList, String socketName,ZygoteServer zygoteServer) {
    ......
    /* Hardcoded command line to start the system server */
    String args[] = {
        "--setuid=1000", //用户id
        "--setgid=1000", //组id
        ......
        "--nice-name=system_server",
        ......
        "com.android.server.SystemServer",
    };
    
    ZygoteConnection.Arguments parsedArgs = null;
    int pid;
    try {
        parsedArgs = new ZygoteConnection.Arguments(args);
        ......
        //fork出system_server子进程,并且设置对应的参数
        pid = Zygote.forkSystemServer(
                parsedArgs.uid, parsedArgs.gid,
                parsedArgs.gids,
                parsedArgs.runtimeFlags,
                null,
                parsedArgs.permittedCapabilities,
                parsedArgs.effectiveCapabilities);
    } catch (IllegalArgumentException ex) {
        throw new RuntimeException(ex);
    }
    //子进程(system_server)
    if (pid == 0) {
        ......
        //所以返回的r不为null,直接执行r.run
        return handleSystemServerProcess(parsedArgs);
    }
    //父进程(zygote),返回的是null,继续往下执行
    return null;
}

ZygoteInit的forkSystemServer方法会调用Zygote的forkSystemServer方法,如果是子进程(system_server)就返回handleSystemServerProcess(),父进程(zygote)就返回null。 frameworks/base/core/java/com/android/internal/os/Zygote.java

代码语言:javascript复制
public static int forkSystemServer(int uid, int gid, int[] gids, int runtimeFlags,int[][] rlimits, long permittedCapabilities, long effectiveCapabilities) {
    ......
    int pid = nativeForkSystemServer(uid, gid, gids, runtimeFlags, 
                rlimits, permittedCapabilities, effectiveCapabilities);
    ......
    return pid;
    }

调用nativeForkSystemServer fork出子进程,nativeForkSystemServer是本地方法,在前面已经通过startReg方法中的register_com_android_internal_os_Zygote将nativeForkSystemServer方法映射到com_android_internal_os_Zygote_nativeForkSystemServer方法上

fork出子进程之后,子进程就开始调用handleSystemServerProcess()方法 frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

代码语言:javascript复制
private static Runnable handleSystemServerProcess(ZygoteConnection.Arguments parsedArgs) {
    ......
    //从环境变量SYSTEMSERVERCLASSPATH获取到SystemServer类文件相应jar包的路径
    final String systemServerClasspath = Os.getenv("SYSTEMSERVERCLASSPATH");
    if (systemServerClasspath != null) {
        //对相应的jar包做dex优化处理
        performSystemServerDexOpt(systemServerClasspath);
        ......
    }

    ......
    ClassLoader cl = null;
    if (systemServerClasspath != null) {
        //创建类加载器classloader
        cl = createPathClassLoader(systemServerClasspath, parsedArgs.targetSdkVersion);

        Thread.currentThread().setContextClassLoader(cl);
    }

    return ZygoteInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl);
}

先从SYSTEMSERVERCLASSPATH环境中获取到SystemServer的classpath,然后使用performSystemServerDexOpt对classpath对应的jar包做dex优化处理。然后创建对应的classloader,后续用来加载SystemServer类,ZygoteInit.zygoteInit()继续往下执行: frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

代码语言:javascript复制
public static final Runnable zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader) {
    ......
    //将标准输出流和标准错误流重定向到Android log中
    RuntimeInit.redirectLogStreams();

    ......
    //本地方法,startReg映射,主要是开启ProcessState线程池,用来进行binder通信
    ZygoteInit.nativeZygoteInit();
    
    return RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader);
}

redirectLogStreams会将标准输入,错误流重定位到Android log中,nativeZygoteInit JNI函数(startReg映射)会开启ProcessState线程池,用来进行binder通信。

继续往下执行RuntimeInit.applicationInit(): frameworks/base/core/java/com/android/internal/os/RuntimeInit.java

代码语言:javascript复制
protected static Runnable applicationInit(int targetSdkVersion, String[] argv,ClassLoader classLoader) {
    ......
    // Remaining arguments are passed to the start class's static main
    return findStaticMain(args.startClass, args.startArgs, classLoader);
}

继续往下执行:

代码语言:javascript复制
/**
 * Invokes a static "main(argv[]) method on class "className".
 * Converts various failing exceptions into RuntimeExceptions, with
 * the assumption that they will then cause the VM instance to exit.
 *
 * @param className Fully-qualified class name
 * @param argv Argument vector for main()
 * @param classLoader the classLoader to load {@className} with
 */
protected static Runnable findStaticMain(String className, String[] argv,ClassLoader classLoader) {
    Class<?> cl;
    ......
    //获取到SystemServer的类类型
    cl = Class.forName(className, true, classLoader);
    ......
    Method m;
    try {
        //获取到main方法的方法id
        m = cl.getMethod("main", new Class[] { String[].class });
    } catch (NoSuchMethodException ex) {
        ......
    } catch (SecurityException ex) {
        ......
    }
    //这个就是③中forkSystemServer的返回值r
    return new MethodAndArgsCaller(m, argv);
}

findStaicMain获取到SystemServer的类类型,并且获取到SystemServer中的main方法的方法id。然后new MethodAndArgsCaller(m,argv)就是③中forkSystemServer的返回值r,让我们看看r.run做了一些什么。 frameworks/base/core/java/com/android/internal/os/RuntimeInit.java

代码语言:javascript复制
static class MethodAndArgsCaller implements Runnable {
    /** method to call */
    private final Method mMethod;
    /** argument array */
    private final String[] mArgs;

    public MethodAndArgsCaller(Method method, String[] args) {
        mMethod = method;
        mArgs = args;
    }

    public void run() {
        try {
            //通过反射调用mMethod静态方法
            mMethod.invoke(null, new Object[] { mArgs });
        } catch (IllegalAccessException ex) {
           ......
        } catch (InvocationTargetException ex) {
            ......
        }
    }
}

由上可知,就是通过反射执行SystemServer类的main方法。众所周知,system_server进程注册和运行着AMS、PMS、PKMS等核心系统服务

④: zygoteServer.runSelectLoop()这轮询会在zygote进程中无限循环,而fork出的子进程(Android应用进程)会退出并继续往下执行

frameworks/base/core/java/com/android/internal/os/ZygoteServer.java

代码语言:javascript复制
//开启zygote进程轮询监听。接收新的socket连接(会创建新的ZygoteConnection)
//并且从这些链接中中读取命令,并且执行
Runnable runSelectLoop(String abiList) {
    ArrayList<FileDescriptor> fds = new ArrayList<FileDescriptor>();
    ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();

    fds.add(mServerSocket.getFileDescriptor());
    peers.add(null);

    while (true) {
        StructPollfd[] pollFds = new StructPollfd[fds.size()];
        for (int i = 0; i < pollFds.length;   i) {
            pollFds[i] = new StructPollfd();
            pollFds[i].fd = fds.get(i);
            pollFds[i].events = (short) POLLIN;
        }
        try {
            //开启轮询
            Os.poll(pollFds, -1);
        } catch (ErrnoException ex) {
            throw new RuntimeException("poll failed", ex);
        }
        for (int i = pollFds.length - 1; i >= 0; --i) {
            if ((pollFds[i].revents & POLLIN) == 0) {
                continue;
            }
            
            if (i == 0) {//如果是新的socket链接请求(建立新连接)
            //新建ZygoteConnection链接
            ZygoteConnection newPeer = acceptCommandPeer(abiList);
            //添加到链接数组中
            peers.add(newPeer);
            //添加到文件描述符数组中
            fds.add(newPeer.getFileDesciptor());
            } else {//如果是之前已经建立的socket链接(在已有连接上)
                try {
                    //获取对应的ZygoteConnection
                    ZygoteConnection connection = peers.get(i);
                    //会执行ZygoteConnection发送过来的命令
                    final Runnable command = connection.processOneCommand(this);

                    if (mIsForkChild) {//子进程走这儿
                        ......
                        //退出,command就是④中的caller
                        return command; 
                    } else {//父进程走这儿,上面是while无限循环,zygote进程永远不会退出
                        ......
                        if (connection.isClosedByPeer()) {
                            connection.closeSocket();
                            peers.remove(i);
                            fds.remove(i);
                        }
                    }
                } catch (Exception e) {
                    ......
                } finally {
                    mIsForkChild = false;
                }
            }
        }
    }
}

上面的流程概括来说,就是会轮询/dev/socket/zygote的socket,如果有新的链接,就新建ZygoteConnection,并将对应的socket fd添加到fds(轮询数组中),继续轮询,如果是新的链接,就重复上面的操作,如果是已经建立的链接,就执行该链接上读取到的command,也就是connection.processOneCommand()方法。

代码语言:javascript复制
Android P之前processOneCommand的方法名是runOnce

frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java

代码语言:javascript复制
Runnable processOneCommand(ZygoteServer zygoteServer) {
    String args[];
    Arguments parsedArgs = null;
    FileDescriptor[] descriptors;
    
    try {
    //读取命令
        args = readArgumentList();
        descriptors = mSocket.getAncillaryFileDescriptors();
    } catch (IOException ex) {
        ......
    }
    
    ......
    parsedArgs = new Arguments(args);
    ......
    
    //fork子进程
    pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,
                parsedArgs.runtimeFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,
                parsedArgs.niceName, fdsToClose, fdsToIgnore, parsedArgs.startChildZygote,
                parsedArgs.instructionSet, parsedArgs.appDataDir);

    try {
        if (pid == 0) {
            // 子进程中(应用进程中)
            zygoteServer.setForkChild();
            ......
            return handleChildProc(parsedArgs, descriptors, childPipeFd,
                    parsedArgs.startChildZygote);
        } else {
            //父进程中(zygote)
            ......
            return null;
        }
    } finally {
        ......
    }
}

从当前链接socket中读取启动命令。如果读取成功,zygote将会fork出子进程,并且返回可以调用启动类的main方法的runnable(也就是④中的caller)

zygoteServer.setForkChild()将mIsForkChild全局变量设为true。 我们接下来分析handleChildProc()方法 frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java

代码语言:javascript复制
private Runnable handleChildProc(Arguments parsedArgs, FileDescriptor[] descriptors,FileDescriptor pipeFd, boolean isZygote) {
    //关闭ZygoteConnection中的socket链接
    closeSocket();
    ......
    if (parsedArgs.niceName != null) {
        Process.setArgV0(parsedArgs.niceName);
    }
    ......
    if (!isZygote) {
        return ZygoteInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs,null /* classLoader */);
    } else {
          ......
    }
}

从ZygoteInit.zygoteInit()开始就和③中分析的代码一模一样了,这里就不重复分析了,③中返回的是可以调用SystemServer的main方法的Runnable,而④中返回的是可以调用ActivityThread的main方法的Runnable。

总结

上面我们提到Zygote进程是第一个java进程,但整篇分析下来,java进程其实也是运行在c 进程之上的,只不过是java虚拟机屏蔽了这一切。zygote进程的启动,是从c 世界一步一步过渡到java世界,每个世界做了自己的准备工作。

c 世界(app_main.cpp入口):

代码语言:javascript复制
动态加载虚拟机动态库,启动java虚拟机
注册JNI本地函数,减轻虚拟机负担
装载ZygoteInit到java虚拟机,正式进入java世界

java世界(ZygoteInit.java入口):

代码语言:javascript复制
绑定套接字,用来接收新Android应用程序运行请求
预加载Android资源,提高应用进程启动速度
启动并运行SystemServer(运行AMS、PMS等核心服务)
处理新Android应用程序运行请求

0 人点赞