zoukankan      html  css  js  c++  java
  • 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.
    ");
            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 <<<<<<
    ",
                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'
    ", 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 "); 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'
    ", 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'
    ", 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 "); if (mJavaVM->DetachCurrentThread() != JNI_OK) ALOGW("Warning: unable to detach main thread "); if (mJavaVM->DestroyJavaVM() != 0) ALOGW("Warning: VM did not shut down cleanly "); }

    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);
            }
        }
  • 相关阅读:
    测试72.思维好题
    pbds:STL平衡树
    测试69。这场因为轻视少了很多分。
    C++ 中的四种类型转换
    C++ 中的static关键字
    codeforces 1269 E K Integers
    P4556 [Vani有约会]雨天的尾巴 (线段树合并)
    P3521 [POI2011]ROT-Tree Rotations (线段树合并)
    codeforces 600E E. Lomsat gelral (线段树合并)
    线段树合并的一些题
  • 原文地址:https://www.cnblogs.com/maogefff/p/7661294.html
Copyright © 2011-2022 走看看