i.mx6 Android5.1.1 Zygote

0. 总结:

0.1 相关源码目录:

framework/base/cmds/app_process/app_main.cpp
frameworks/base/core/jni/AndroidRuntime.cpp
frameworks/base/core/jni/com_android_internal_os_ZygoteInit.cpp
frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java

0.2 流程总结:

1. init.rc启动进入app_main.cpp
2. app_main.cpp查看init.rc给的相关参数,进行处理进入AndroidRuntime.cpp
3. AndroidRuntime.cpp启动虚拟机,初始化JNI,然后根据函数名通过反射机制加载zygote,进入JAVA层zygote的Zygote.java
4. 注册socket,加载各种资源(类,共享资源,共享库),启动SystemServer服务,循环接收socket,创建新进程

1. native层init.rc(进入zygote)

复制代码
#名字为zygote的服务,可执行文件路径为/system/bin/app_process,后面几个为带的参数
#建立socket通讯
#运行后,只执行一次的几个服务
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 media onrestart restart netd
复制代码

2. native层的app_main.cpp

/framework/base/cmds/app_process/app_main.cpp

 int main(int argc, char* const argv[]){   //参数argv为:-Xzygote /system/bin --zygote --start-system-server
  if
(prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) < 0) { // Older kernels don't understand PR_SET_NO_NEW_PRIVS and return // EINVAL. Don't die on such kernels. if (errno != EINVAL) { LOG_ALWAYS_FATAL("PR_SET_NO_NEW_PRIVS failed: %s", strerror(errno)); return 12; } } AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv)); // Process command line arguments // ignore argv[0] argc--; argv++; int i; for (i = 0; i < argc; i++) { if (argv[i][0] != '-') { break; } if (argv[i][1] == '-' && argv[i][2] == 0) { ++i; // Skip --. break; } runtime.addOption(strdup(argv[i])); } // Parse runtime arguments. Stop at first unrecognized option. bool zygote = false; bool startSystemServer = false; bool application = false; String8 niceName; String8 className; ++i; // Skip unused "parent dir" argument. while (i < argc) {
const char* arg = argv[i++]; if (strcmp(arg, "--zygote") == 0) {
       
//这里我们有 zygote = true; niceName = ZYGOTE_NICE_NAME; } else if (strcmp(arg, "--start-system-server") == 0) { startSystemServer = true; //这里我们有 } else if (strcmp(arg, "--application") == 0) { application = true; //这里是进入应用,我们没有 } else if (strncmp(arg, "--nice-name=", 12) == 0) { niceName.setTo(arg + 12); //没有 } else if (strncmp(arg, "--", 2) != 0break; } else { --i; break; } }    Vector<String8>if (!className.isEmpty()) { // We're not in zygote mode, the only argument we need to pass // to RuntimeInit is the application argument. // // The Remainder of args get passed to startup class main(). Make // copies of them before we overwrite them with the process name. args.add(application ? String8("application") : String8("tool")); runtime.setClassNameAndArgs(className, argc - i, argv + i); } else { // We're in zygote mode. maybeCreateDalvikCache();     //添加所有参数 } } if (!niceName.isEmpty()) { //没有,不进入 runtime.setArgv0(niceName.string()); set_process_name(niceName.string()); } if (zygote) {
    
//进入这里,启动zygote
     //args为:
start-system-server --abi-list=armeabi-v71,armeabi -Xzygote /system/bin --zygote --start-system-server
   runtime.start("com.android.internal.os.ZygoteInit", args);
    } else if (className) {
        runtime.start("com.android.internal.os.RuntimeInit", args);
    } else {
        fprintf(stderr, "Error: no class name or --zygote supplied.\n");
        app_usage();
        LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
        return 10;
    }
}

 

3. native层的AndroidRuntime

frameworks/base/core/jni/AndroidRuntime.cpp

接着往下看:runtime.start

记住,我们传进来的className为:com.android.internal.os.ZygoteInit

参数为options为:start-system-server --abi-list=armeabi-v71,armeabi -Xzygote /system/bin --zygote --start-system-server

void AndroidRuntime::start(const char* className, const Vector<String8>& options)
{
    ALOGD(">>>>>> START %s uid %d <<<<<<\n",
            className != NULL ? className : "(unknown)", getuid());

    static const String8 startSystemServer("start-system-server");

    /*
     * 'startSystemServer == true' means runtime is obsolete and not run from
     * init.rc anymore, so we print out the boot start event here.
     */
    for (size_t i = 0; i < options.size(); ++i) {
        if (options[i] == startSystemServer) {//我们参数有,进入
           /* track our progress through the boot sequence */
           const int LOG_BOOT_PROGRESS_START = 3000;
           LOG_EVENT_LONG(LOG_BOOT_PROGRESS_START,  ns2ms(systemTime(SYSTEM_TIME_MONOTONIC)));
        }
    }
   //修改环境变量ANDROID_ROOT: /system
    const char* rootDir = getenv("ANDROID_ROOT");
    if (rootDir == NULL) {
        rootDir = "/system";
        if (!hasDir("/system")) {
            LOG_FATAL("No root directory specified, and /android does not exist.");
            return;
        }
        setenv("ANDROID_ROOT", rootDir, 1);
    }

    //const char* kernelHack = getenv("LD_ASSUME_KERNEL");
    //ALOGD("Found LD_ASSUME_KERNEL='%s'\n", kernelHack);

    /* start the virtual machine */
    //启动虚拟机,以后再分析
JniInvocation jni_invocation; jni_invocation.Init(NULL); JNIEnv
* env; if (startVm(&mJavaVM, &env) != 0) { return; } onVmCreated(env); /* * Register android functions.初始化JNI函数 */ if (startReg(env) < 0) { ALOGE("Unable to register all android natives\n"); return; } /* * We want to call main() with a String array with arguments in it. * At present we have two arguments, the class name and an option string. * Create an array to hold them. 下面都是JNI的用法了,具体去查看JNI那章的博客 */ jclass stringClass; jobjectArray strArray; jstring classNameStr;   /*
  *下面这一串代码就是通过JNI找到ZygoteInit.cpp,然后跳进去,流程是:
  *1.找到String类,然后创建一个String = com.android.internal.os.ZygoteInit(这个变量是className参数传进来的)
  *2.将com.android.internal.os.ZygoteInit转换成com/android/internal/os/ZygoteInit
  *3.查找上面的
com/android/internal/os/ZygoteInit这个类中的main函数,
  *4.跳入main中
  */
  stringClass = env->FindClass("java/lang/String");
  assert(stringClass != NULL);
    strArray = env->NewObjectArray(options.size() + 1, stringClass, NULL);
    assert(strArray != NULL);
    classNameStr = env->NewStringUTF(className);
    assert(classNameStr != NULL);
    env->SetObjectArrayElement(strArray, 0, classNameStr);
  
    for (size_t i = 0; i < options.size(); ++i) {
        jstring optionsStr = env->NewStringUTF(options.itemAt(i).string());
        assert(optionsStr != NULL);
        env->SetObjectArrayElement(strArray, i + 1, optionsStr);
    }

    /*
     * Start VM.  This thread becomes the main thread of the VM, and will
     * not return until the VM exits.
     */
    char* slashClassName = toSlashClassName(className);
    jclass startClass = env->FindClass(slashClassName);
    if (startClass == NULL) {
        ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);
        /* keep going */
    } else {
        jmethodID startMeth = env->GetStaticMethodID(startClass, "main",
            "([Ljava/lang/String;)V");
        if (startMeth == NULL) {
            ALOGE("JavaVM unable to find main() in '%s'\n", className);
            /* keep going */
        } else {
       
//在这里通过反射,正式进入JAVA层的zygote:根据上面的注释,可知这里的startClass为Zygote, startMeth为main
       //strArry为参数:start-system-server --abi-list=armeabi-v71,armeabi -Xzygote /system/bin --zygote --start-system-server(不是很确定,应该是这个)
env->CallStaticVoidMethod(startClass, startMeth, strArray); #if 0 if (env->ExceptionCheck()) threadExitUncaughtException(env); #endif } } free(slashClassName); ALOGD("Shutting down VM\n"); if (mJavaVM->DetachCurrentThread() != JNI_OK) ALOGW("Warning: unable to detach main thread\n"); if (mJavaVM->DestroyJavaVM() != 0) ALOGW("Warning: VM did not shut down cleanly\n"); }

4. JAVA层的Zygote.java

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

ZygoteInit.java函数中的main中

参数如上所分析的argv为:start-system-server --abi-list=armeabi-v71,armeabi -Xzygote /system/bin --zygote --start-system-server

public static void main(String argv[]) {
        try {
            // Start profiling the zygote initialization.
       // 不懂,以后看
SamplingProfilerIntegration.start(); boolean startSystemServer = false; String socketName = "zygote"; String abiList = null; for (int i = 1; i < argv.length; i++) { if ("start-system-server".equals(argv[i])) { startSystemServer = true; //看上面的参数,这里有 } else if (argv[i].startsWith(ABI_LIST_ARG)) { abiList = argv[i].substring(ABI_LIST_ARG.length()); //--abi-list: 这里有 } else if (argv[i].startsWith(SOCKET_NAME_ARG)) { socketName = argv[i].substring(SOCKET_NAME_ARG.length()); //这个没有 } else { throw new RuntimeException("Unknown command line argument: " + argv[i]); } } if (abiList == null) { throw new RuntimeException("No ABI list supplied."); }        //注册zygote的socket,我们socketname为默认的zygote registerZygoteSocket(socketName); EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START, SystemClock.uptimeMillis());
       //注意:这个很重要,加载各种资源 preload(); EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END, SystemClock.uptimeMillis());
// Finish profiling the zygote initialization. SamplingProfilerIntegration.writeZygoteSnapshot(); // Do an initial gc to clean up after startup gc(); // Disable tracing so that forked processes do not inherit stale tracing tags from // Zygote. Trace.setTracingEnabled(false);        //在这里启动systemserver if (startSystemServer) { startSystemServer(abiList, socketName); } Log.i(TAG, "Accepting command socket connections"); runSelectLoop(abiList); closeServerSocket(); } catch (MethodAndArgsCaller caller) { caller.run(); } catch (RuntimeException ex) { Log.e(TAG, "Zygote died with exception", ex); closeServerSocket(); throw ex; } }

 

5. JAVA层的preload

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

static void preload() {
        Log.d(TAG, "begin preload");
        preloadClasses();   //加载类
        preloadResources(); //加载资源
        preloadOpenGL();    //加载OpenGL,这个是跟显示有关的图形库
        preloadSharedLibraries(); //加载共享库
        // Ask the WebViewFactory to do any initialization that must run in the zygote process,
        // for memory sharing purposes.
        WebViewFactory.prepareWebViewInZygote();     //加载???,等会再说
        Log.d(TAG, "end preload");  //打印log,显示加载完成
    }

 

5.1 加载类preloadClasses

 

这里用到的反射,忘记了可以看看:语言方面的知识

 

private static final String PRELOADED_CLASSES = "/system/etc/preloaded-classes";

 

private static void preloadClasses() {
        final VMRuntime runtime = VMRuntime.getRuntime();

        InputStream is;
        try {
            is = new FileInputStream(PRELOADED_CLASSES);  //在这里面是预加载的类
        } catch (FileNotFoundException e) {
            Log.e(TAG, "Couldn't find " + PRELOADED_CLASSES + ".");
            return;
        }

        Log.i(TAG, "Preloading classes...");
        long startTime = SystemClock.uptimeMillis();

        // Drop root perms while running static initializers.
        setEffectiveGroup(UNPRIVILEGED_GID);
        setEffectiveUser(UNPRIVILEGED_UID);

        // Alter the target heap utilization.  With explicit GCs this
        // is not likely to have any effect.
        float defaultUtilization = runtime.getTargetHeapUtilization();
        runtime.setTargetHeapUtilization(0.8f);

        // Start with a clean slate.
        System.gc();
        runtime.runFinalizationSync();
        Debug.startAllocCounting();

        try {
            BufferedReader br
                = new BufferedReader(new InputStreamReader(is), 256);

            int count = 0;
            String line;
            while ((line = br.readLine()) != null) {   //一行一行的读取出来
                // Skip comments and blank lines.
                line = line.trim();
                if (line.startsWith("#") || line.equals("")) {
                    continue;
                }

                try {
                    if (false) {
                        Log.v(TAG, "Preloading " + line + "...");
                    }
                    Class.forName(line);   //注意:在这里加载的,是通过类名进行反射
                    if (Debug.getGlobalAllocSize() > PRELOAD_GC_THRESHOLD) {
                        if (false) {
                            Log.v(TAG,
                                " GC at " + Debug.getGlobalAllocSize());
                        }
                        System.gc();
                        runtime.runFinalizationSync();
                        Debug.resetGlobalAllocSize();
                    }
                    count++;
                } catch (ClassNotFoundException e) {
                    Log.w(TAG, "Class not found for preloading: " + line);
                } catch (UnsatisfiedLinkError e) {
                    Log.w(TAG, "Problem preloading " + line + ": " + e);
                } catch (Throwable t) {
                    Log.e(TAG, "Error preloading " + line + ".", t);
                    if (t instanceof Error) {
                        throw (Error) t;
                    }
                    if (t instanceof RuntimeException) {
                        throw (RuntimeException) t;
                    }
                    throw new RuntimeException(t);
                }
            }

            Log.i(TAG, "...preloaded " + count + " classes in "
                    + (SystemClock.uptimeMillis()-startTime) + "ms.");
        } catch (IOException e) {
            Log.e(TAG, "Error reading " + PRELOADED_CLASSES + ".", e);
        } finally {
            IoUtils.closeQuietly(is);
            // Restore default.
            runtime.setTargetHeapUtilization(defaultUtilization);

            // Fill in dex caches with classes, fields, and methods brought in by preloading.
            runtime.preloadDexCaches();

            Debug.stopAllocCounting();

            // Bring back root. We'll need it later.
            setEffectiveUser(ROOT_UID);
            setEffectiveGroup(ROOT_GID);
        }
    }

 

5.2 加载共享资源preloadResources

private static void preloadResources() {
        final VMRuntime runtime = VMRuntime.getRuntime();

        Debug.startAllocCounting();
        try {
            System.gc();
            runtime.runFinalizationSync();
            mResources = Resources.getSystem();
            mResources.startPreloading();
            if (PRELOAD_RESOURCES) {
                Log.i(TAG, "Preloading resources...");

                long startTime = SystemClock.uptimeMillis();
                TypedArray ar = mResources.obtainTypedArray(
                        com.android.internal.R.array.preloaded_drawables);
                int N = preloadDrawables(runtime, ar);
                ar.recycle();
                Log.i(TAG, "...preloaded " + N + " resources in "
                        + (SystemClock.uptimeMillis()-startTime) + "ms.");

                startTime = SystemClock.uptimeMillis();
                ar = mResources.obtainTypedArray(
                        com.android.internal.R.array.preloaded_color_state_lists);
                N = preloadColorStateLists(runtime, ar);
                ar.recycle();
                Log.i(TAG, "...preloaded " + N + " resources in "
                        + (SystemClock.uptimeMillis()-startTime) + "ms.");
            }
            mResources.finishPreloading();
        } catch (RuntimeException e) {
            Log.w(TAG, "Failure preloading resources", e);
        } finally {
            Debug.stopAllocCounting();
        }
    }

 

5.3 加载共享库

private static void preloadSharedLibraries() {
        Log.i(TAG, "Preloading shared libraries...");
        System.loadLibrary("android");
        System.loadLibrary("compiler_rt");
        System.loadLibrary("jnigraphics");
    }

 

5.4 加载prepareWebViewInZygote(不懂,预留)

 

6. socket

6.1 registerZygoteSocket

private static void registerZygoteSocket(String socketName) {
        if (sServerSocket == null) {
            int fileDesc;
        //fullSocketName=ANDROID_SOCKET_zygote,不过,我查了一下我们的代码,没有这个环境变量????不知道为什么
final String fullSocketName = ANDROID_SOCKET_PREFIX + socketName;
try {
                String env = System.getenv(fullSocketName); //ANDROID_SOCKET_zygote
                fileDesc = Integer.parseInt(env);
            } catch (RuntimeException ex) {
                throw new RuntimeException(fullSocketName + " unset or invalid", ex);
            }

            try {
          //创建一个socket本地服务的对象,这里的sServerSocket是一个静态属性,我们后面会用到 sServerSocket
= new LocalServerSocket( createFileDescriptor(fileDesc)); } catch (IOException ex) { throw new RuntimeException( "Error binding to local socket '" + fileDesc + "'", ex); } } }

 

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

private static void registerZygoteSocket(String socketName) {
        if (sServerSocket == null) {
            int fileDesc;
            final String fullSocketName = ANDROID_SOCKET_PREFIX + socketName;
            try {
                String env = System.getenv(fullSocketName); //ANDROID_SOCKET_zygote
                fileDesc = Integer.parseInt(env);
            } catch (RuntimeException ex) {
                throw new RuntimeException(fullSocketName + " unset or invalid", ex);
            }

            try {
         //这里的LocalServerSocket创建了一个对象,然后绑定socket,并listen
         //createFileDescriptor是一个本地函数,通过JNI创建一个文件,并返回fd,如后面所示
sServerSocket
= new LocalServerSocket( createFileDescriptor(fileDesc)); } catch (IOException ex) { throw new RuntimeException( "Error binding to local socket '" + fileDesc + "'", ex); } } }

 

6.2 com_android_internal_os_ZygoteInit.cpp

frameworks/base/core/jni/com_android_internal_os_ZygoteInit.cpp

static JNINativeMethod gMethods[] = {
    /* name, signature, funcPtr */
    { "setreuid", "(II)I",
      (void*) com_android_internal_os_ZygoteInit_setreuid },
    { "setregid", "(II)I",
      (void*) com_android_internal_os_ZygoteInit_setregid },
    { "setpgid", "(II)I",
      (void *) com_android_internal_os_ZygoteInit_setpgid },
    { "getpgid", "(I)I",
      (void *) com_android_internal_os_ZygoteInit_getpgid },
    { "reopenStdio",
        "(Ljava/io/FileDescriptor;Ljava/io/FileDescriptor;"
        "Ljava/io/FileDescriptor;)V",
            (void *) com_android_internal_os_ZygoteInit_reopenStdio},
    { "setCloseOnExec", "(Ljava/io/FileDescriptor;Z)V",
        (void *)  com_android_internal_os_ZygoteInit_setCloseOnExec},
    { "selectReadable", "([Ljava/io/FileDescriptor;)I",
        (void *) com_android_internal_os_ZygoteInit_selectReadable },
    { "createFileDescriptor", "(I)Ljava/io/FileDescriptor;",
        (void *) com_android_internal_os_ZygoteInit_createFileDescriptor }    /*这里就是上面所调用到的函数*/
};

 

static jobject com_android_internal_os_ZygoteInit_createFileDescriptor (
        JNIEnv *env, jobject clazz, jint fd)
{
    return jniCreateFileDescriptor(env, fd);    //创建文件描述符
}

 

7. 启动SystemServer

这个函数是调用SystemServer.我就放入SystemServer的博客更合适一点

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

private static boolean startSystemServer(String abiList, String socketName)
            throws MethodAndArgsCaller, RuntimeException {
        long capabilities = posixCapabilitiesAsBits(
            OsConstants.CAP_BLOCK_SUSPEND,
            OsConstants.CAP_KILL,
            OsConstants.CAP_NET_ADMIN,
            OsConstants.CAP_NET_BIND_SERVICE,
            OsConstants.CAP_NET_BROADCAST,
            OsConstants.CAP_NET_RAW,
            OsConstants.CAP_SYS_MODULE,
            OsConstants.CAP_SYS_NICE,
            OsConstants.CAP_SYS_RESOURCE,
            OsConstants.CAP_SYS_TIME,
            OsConstants.CAP_SYS_TTY_CONFIG
        );
        /* Hardcoded command line to start the system server */
        String args[] = {
            "--setuid=1000",
            "--setgid=1000",
            "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1032,3001,3002,3003,3006,3007",
            "--capabilities=" + capabilities + "," + capabilities,
            "--runtime-init",
            "--nice-name=system_server",
            "com.android.server.SystemServer",
        };
        ZygoteConnection.Arguments parsedArgs = null;

        int pid;

        try {
            parsedArgs = new ZygoteConnection.Arguments(args);
            ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);
            ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs);

            /* Request to fork the system server process */
       //通过fork创建子进程
pid = Zygote.forkSystemServer( parsedArgs.uid, parsedArgs.gid, parsedArgs.gids, parsedArgs.debugFlags, null, parsedArgs.permittedCapabilities, parsedArgs.effectiveCapabilities); } catch (IllegalArgumentException ex) { throw new RuntimeException(ex); } /* For child process */ if (pid == 0) { //从子进程跳入systemserver if (hasSecondZygote(abiList)) { waitForSecondaryZygote(socketName); } handleSystemServerProcess(parsedArgs); } return true; }

 

8. loop循环接收其他进程,并创建新进程

8.1 runSelectLoop

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

这里用到的socket的select模式,可以查看:Linux知识点

private static void runSelectLoop(String abiList) throws MethodAndArgsCaller {
        ArrayList<FileDescriptor> fds = new ArrayList<FileDescriptor>();
        ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();
        FileDescriptor[] fdArray = new FileDescriptor[4];   //新建一个数组
     //拿到fd(也就是我们之前socket创建的),并添加到容器
        fds.add(sServerSocket.getFileDescriptor());
        peers.add(null);

        int loopCount = GC_LOOP_COUNT;
        while (true) {
            int index;

            /*
             * Call gc() before we block in select().
             * It's work that has to be done anyway, and it's better
             * to avoid making every child do it.  It will also
             * madvise() any free memory as a side-effect.
             *
             * Don't call it every time, because walking the entire
             * heap is a lot of overhead to free a few hundred bytes.
             */
            if (loopCount <= 0) {
                gc();
                loopCount = GC_LOOP_COUNT;
            } else {
                loopCount--;
            }


            try {
         //转换为数组 fdArray
= fds.toArray(fdArray);
          //调用本地函数去select,去监听数组fdArray,如后面所说 index
= selectReadable(fdArray); } catch (IOException ex) { throw new RuntimeException("Error in select()", ex); } if (index < 0) { throw new RuntimeException("Error in select()"); //异常抛出 } else if (index == 0) {
         //当select到了有可读数据之后,通过accept去监听
         //这里的abiList是之前参数传进来的:--abi-list=armeabi-v71,armeabi
         //新建以后再添加,监听
ZygoteConnection newPeer
= acceptCommandPeer(abiList); peers.add(newPeer); fds.add(newPeer.getFileDescriptor()); } else { boolean done;
         //当收到select以后,根据select索引,运行,具体查看章节9 done
= peers.get(index).runOnce(); if (done) { peers.remove(index); fds.remove(index); } } } }

 

8.2 com_android_internal_os_ZygoteInit.cpp

frameworks/base/core/jni/com_android_internal_os_ZygoteInit.cpp

static JNINativeMethod gMethods[] = {
    /* name, signature, funcPtr */
    { "setreuid", "(II)I",
      (void*) com_android_internal_os_ZygoteInit_setreuid },
    { "setregid", "(II)I",
      (void*) com_android_internal_os_ZygoteInit_setregid },
    { "setpgid", "(II)I",
      (void *) com_android_internal_os_ZygoteInit_setpgid },
    { "getpgid", "(I)I",
      (void *) com_android_internal_os_ZygoteInit_getpgid },
    { "reopenStdio",
        "(Ljava/io/FileDescriptor;Ljava/io/FileDescriptor;"
        "Ljava/io/FileDescriptor;)V",
            (void *) com_android_internal_os_ZygoteInit_reopenStdio},
    { "setCloseOnExec", "(Ljava/io/FileDescriptor;Z)V",
        (void *)  com_android_internal_os_ZygoteInit_setCloseOnExec},
    { "selectReadable", "([Ljava/io/FileDescriptor;)I",
        (void *) com_android_internal_os_ZygoteInit_selectReadable },   //这一个是监听可读
    { "createFileDescriptor", "(I)Ljava/io/FileDescriptor;",
        (void *) com_android_internal_os_ZygoteInit_createFileDescriptor }
};

 

在这里关于select的用法和JNI的相关用法可以查看我的博客:

预留。。。

预留。。。

static jint com_android_internal_os_ZygoteInit_selectReadable (
        JNIEnv *env, jobject clazz, jobjectArray fds)
{
    if (fds == NULL) {
        jniThrowNullPointerException(env, "fds == null");
        return -1;
    }

    jsize length = env->GetArrayLength(fds);
    fd_set fdset;

    if (env->ExceptionOccurred() != NULL) {
        return -1;
    }

    FD_ZERO(&fdset);

    int nfds = 0;
    for (jsize i = 0; i < length; i++) {
        jobject fdObj = env->GetObjectArrayElement(fds, i);
        if  (env->ExceptionOccurred() != NULL) {
            return -1;
        }
        if (fdObj == NULL) {
            continue;
        }
        int fd = jniGetFDFromFileDescriptor(env, fdObj);
        if  (env->ExceptionOccurred() != NULL) {
            return -1;
        }

        FD_SET(fd, &fdset);

        if (fd >= nfds) {
            nfds = fd + 1;
        }
    }

    int err;
    do {
        err = select (nfds, &fdset, NULL, NULL, NULL);    //在这里监听
    } while (err < 0 && errno == EINTR);

    if (err < 0) {
        jniThrowIOException(env, errno);
        return -1;
    }

    for (jsize i = 0; i < length; i++) {
        jobject fdObj = env->GetObjectArrayElement(fds, i);
        if  (env->ExceptionOccurred() != NULL) {
            return -1;
        }
        if (fdObj == NULL) {
            continue;
        }
        int fd = jniGetFDFromFileDescriptor(env, fdObj);
        if  (env->ExceptionOccurred() != NULL) {
            return -1;
        }
        if (FD_ISSET(fd, &fdset)) {
            return (jint)i;
        }
    }
    return -1;
}

 

9. runOnce启动新进程(没有看的很懂,之后再分析)

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

从之前的

done = peers.get(index).runOnce();

然后查看peers类型

ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();

搜索ZygoteConnection可以找到

boolean runOnce() throws ZygoteInit.MethodAndArgsCaller {

        String args[];
        Arguments parsedArgs = null;
        FileDescriptor[] descriptors;

        long startTime = SystemClock.elapsedRealtime();

        try {
            args = readArgumentList();
            descriptors = mSocket.getAncillaryFileDescriptors();
        } catch (IOException ex) {
            Log.w(TAG, "IOException on command socket " + ex.getMessage());
            closeSocket();
            return true;
        }

        checkTime(startTime, "zygoteConnection.runOnce: readArgumentList");
        if (args == null) {
            // EOF reached.
            closeSocket();
            return true;
        }

        /** the stderr of the most recent request, if avail */
        PrintStream newStderr = null;

        if (descriptors != null && descriptors.length >= 3) {
            newStderr = new PrintStream(
                    new FileOutputStream(descriptors[2]));
        }

        int pid = -1;
        FileDescriptor childPipeFd = null;
        FileDescriptor serverPipeFd = null;

        try {
            parsedArgs = new Arguments(args);

            if (parsedArgs.abiListQuery) {
                return handleAbiListQuery();
            }

            if (parsedArgs.permittedCapabilities != 0 || parsedArgs.effectiveCapabilities != 0) {
                throw new ZygoteSecurityException("Client may not specify capabilities: " +
                        "permitted=0x" + Long.toHexString(parsedArgs.permittedCapabilities) +
                        ", effective=0x" + Long.toHexString(parsedArgs.effectiveCapabilities));
            }


            applyUidSecurityPolicy(parsedArgs, peer, peerSecurityContext);
            applyRlimitSecurityPolicy(parsedArgs, peer, peerSecurityContext);
            applyInvokeWithSecurityPolicy(parsedArgs, peer, peerSecurityContext);
            applyseInfoSecurityPolicy(parsedArgs, peer, peerSecurityContext);

            checkTime(startTime, "zygoteConnection.runOnce: apply security policies");

            applyDebuggerSystemProperty(parsedArgs);
            applyInvokeWithSystemProperty(parsedArgs);

            checkTime(startTime, "zygoteConnection.runOnce: apply security policies");

            int[][] rlimits = null;

            if (parsedArgs.rlimits != null) {
                rlimits = parsedArgs.rlimits.toArray(intArray2d);
            }

            if (parsedArgs.runtimeInit && parsedArgs.invokeWith != null) {
                FileDescriptor[] pipeFds = Os.pipe();
                childPipeFd = pipeFds[1];
                serverPipeFd = pipeFds[0];
                ZygoteInit.setCloseOnExec(serverPipeFd, true);
            }

            /**
             * In order to avoid leaking descriptors to the Zygote child,
             * the native code must close the two Zygote socket descriptors
             * in the child process before it switches from Zygote-root to
             * the UID and privileges of the application being launched.
             *
             * In order to avoid "bad file descriptor" errors when the
             * two LocalSocket objects are closed, the Posix file
             * descriptors are released via a dup2() call which closes
             * the socket and substitutes an open descriptor to /dev/null.
             */

            int [] fdsToClose = { -1, -1 };

            FileDescriptor fd = mSocket.getFileDescriptor();

            if (fd != null) {
                fdsToClose[0] = fd.getInt$();
            }

            fd = ZygoteInit.getServerSocketFileDescriptor();

            if (fd != null) {
                fdsToClose[1] = fd.getInt$();
            }

            fd = null;

            checkTime(startTime, "zygoteConnection.runOnce: preForkAndSpecialize");
            pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,
                    parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,
                    parsedArgs.niceName, fdsToClose, parsedArgs.instructionSet,
                    parsedArgs.appDataDir);
            checkTime(startTime, "zygoteConnection.runOnce: postForkAndSpecialize");
        } catch (IOException ex) {
            logAndPrintError(newStderr, "Exception creating pipe", ex);
        } catch (ErrnoException ex) {
            logAndPrintError(newStderr, "Exception creating pipe", ex);
        } catch (IllegalArgumentException ex) {
            logAndPrintError(newStderr, "Invalid zygote arguments", ex);
        } catch (ZygoteSecurityException ex) {
            logAndPrintError(newStderr,
                    "Zygote security policy prevents request: ", ex);
        }

        try {
            if (pid == 0) {
                // in child
                IoUtils.closeQuietly(serverPipeFd);
                serverPipeFd = null;
                handleChildProc(parsedArgs, descriptors, childPipeFd, newStderr);

                // should never get here, the child is expected to either
                // throw ZygoteInit.MethodAndArgsCaller or exec().
                return true;
            } else {
                // in parent...pid of < 0 means failure
                IoUtils.closeQuietly(childPipeFd);
                childPipeFd = null;
                return handleParentProc(pid, descriptors, serverPipeFd, parsedArgs);
            }
        } finally {
            IoUtils.closeQuietly(childPipeFd);
            IoUtils.closeQuietly(serverPipeFd);
        }
    }

 

posted on 2017-10-27 18:07  maogefff  阅读(338)  评论(0编辑  收藏  举报

导航