当前位置:   article > 正文

Zygote 启动过程_zygote : java.lang.runtimeexception: socket unset

zygote : java.lang.runtimeexception: socket unset or invalid: android_socket

1.在Android系统中,所有应用程序进程以及系统服务进程都是由Zygote进程孕育(fork)出来的。
  而在Linux系统中,所有的进程都是init进程的子孙进程,Zygote也是由init进程创建的。
  在system/core/rootdir/init.rc中Zygote定义的导入
  ........
  import /init.environ.rc
  import /init.usb.rc
  import /init.${ro.hardware}.rc
  import /init.${ro.zygote}.rc
  import /init.trace.rc
  ........
 
  在system/core/rootdir/init.zygote64.rc中Zygote定义
  #创建一个名为"zygote"的进程,这个zygote进程要执行的程序是/system/bin/app_process64,后面是要传给app_process的参数
  #--zygote 在zygote模式启动, --start-system-server 启动系统服务
  service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server
  class main #指定分组为main,同一分组的服务,可以统一启动与停止
  socket zygote stream 660 root system #创建一个unix域的名为/dev/socket/zygote的套接字,并传递它的文件描述符给已启动的进程.
  onrestart write /sys/android_power/request_state wake #zygote进程重启时执行/sys/android_power/request_state wake
  onrestart write /sys/power/state on #zygote进程重启时/sys/power/state on
  onrestart restart media #zygote进程重启时重启media服务
  onrestart restart netd #zygote进程重启时重启netd服务

2.由1可以看出Zygote进程执行的便是/system/bin/app_process64,对应的源码是frameworks/base/cmds/app_process/app_main.cpp,入口函数是main
//frameworks/base/cmds/app_process/app_main.cpp
........
namespace android {
 ........
 static AndroidRuntime* gCurRuntime = NULL; // 当前的AndroidRuntime对象
 ........
 AndroidRuntime::AndroidRuntime(char* argBlockStart, const size_t argBlockLength) :
        mExitWithoutCleanup(false),
        mArgBlockStart(argBlockStart),
        mArgBlockLength(argBlockLength)
 {
     ........
     assert(gCurRuntime == NULL);        // one per process
     gCurRuntime = this;
 }
 ........
 AndroidRuntime* AndroidRuntime::getRuntime()
 {
     return gCurRuntime;
 }
 ........
 void AndroidRuntime::start(const char* className, const Vector<String8>& options)
 {
     ........
     /* start the virtual machine */
     JniInvocation jni_invocation;
     jni_invocation.Init(NULL);
     JNIEnv* env;
     if (startVm(&mJavaVM, &env) != 0) { // 调用函数startVM启动虚拟机
         return;
     }
     onVmCreated(env);
    
     if (startReg(env) < 0) { // 调用函数startReg注册JNI方法
         ALOGE("Unable to register all android natives\n");
         return;
     }
     ........
     // 调用com.android.internal.os.ZygoteInit类的main函数
     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 {
             env->CallStaticVoidMethod(startClass, startMeth, strArray); // 调用main函数
 
  #if 0
             if (env->ExceptionCheck())
                 threadExitUncaughtException(env);
  #endif
         }
     }
     free(slashClassName);
     ........
 }
 ........
}
........
 
//frameworks/base/cmds/app_process/app_main.cpp
........
namespace android {
   ........
   class AppRuntime : public AndroidRuntime // 继承与/frameworks/base/core/jni/AndroidRuntime.cpp
   {
       ........
   }
   ........
}
........
using namespace android;
........

int main(int argc, char* const argv[])
{
    ........
    AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv)); // 定义一个AppRuntime的对象
    ........
    while (i < argc) {
        const char* arg = argv[i++];
        if (strcmp(arg, "--zygote") == 0) { // 在init.rc中设置了app_process启动参数--zygote
            zygote = true;
            niceName = ZYGOTE_NICE_NAME;
        } else if (strcmp(arg, "--start-system-server") == 0) { // 在init.rc中设置了app_process启动参数--start-system-server
            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) != 0) {
            className.setTo(arg);
            break;
        } else {
            --i;
            break;
        }
    }
    ........
    if (zygote) {
        runtime.start("com.android.internal.os.ZygoteInit", args); // 调用父类的start启动ZygoteInit
    } 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.ZygoteInit类定义在frameworks/base/core/java/com/android/internal/os/ZygoteInit.java文件中
public class ZygoteInit {
    ........
  private static final String ANDROID_SOCKET_ENV = "ANDROID_SOCKET_zygote";
  ........
    private static void registerZygoteSocket(String socketName) {
        if (sServerSocket == null) {
            int fileDesc;
            final String fullSocketName = ANDROID_SOCKET_PREFIX + socketName; // ANDROID_SOCKET_zygote
            try {
                String env = System.getenv(fullSocketName); // 提供环境变量ANDROID_SOCKET_zygote获取文件/dev/socket/zygote的文件描述符
                fileDesc = Integer.parseInt(env);
            } catch (RuntimeException ex) {
                throw new RuntimeException(fullSocketName + " unset or invalid", ex);
            }

            try {
                sServerSocket = new LocalServerSocket(createFileDescriptor(fileDesc));
            } catch (IOException ex) {
                throw new RuntimeException("Error binding to local socket '" + fileDesc + "'", ex);
            }
        }
    }
    ........
    private static boolean startSystemServer(String abiList, String socketName)
            throws MethodAndArgsCaller, RuntimeException {
        ........
        try {
            ........
            pid = Zygote.forkSystemServer( // 提供Zygote的forkSystemServer函数来创建一个新的进程来启动SystemServer组件
                    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) { // 返回值pid等0的地方就是新的进程要执行的路径,即新创建的进程会执行handleSystemServerProcess函数
            if (hasSecondZygote(abiList)) {
                waitForSecondaryZygote(socketName);
            }

            handleSystemServerProcess(parsedArgs);
        }

        return true;
    }
    ........
    private static void handleSystemServerProcess(
            ZygoteConnection.Arguments parsedArgs)
            throws ZygoteInit.MethodAndArgsCaller {
        closeServerSocket(); // 由Zygote进程创建的子进程继承Zygote进程在前面创建的Socket文件描述符,而这里的子进程又不会用到它,调用closeServerSocket函数来关闭
        ........
        final String systemServerClasspath = Os.getenv("SYSTEMSERVERCLASSPATH");
        if (systemServerClasspath != null) {
            performSystemServerDexOpt(systemServerClasspath);// 对Zygote进程启动的SystemServer进行Dex优化
        }
        ........
        if (parsedArgs.invokeWith != null) {
            ........
        } else {
            ........
            RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl); // 调用RuntimeInit.zygoteInit函数来进一步执行启动SystemServer组件的操作
        }
    }
    ........
    public static void main(String argv[]) {
        try {
            ........
            boolean startSystemServer = false;
            String socketName = "zygote";
            String abiList = null;
            for (int i = 1; i < argv.length; i++) {
                if ("start-system-server".equals(argv[i])) { // 在init.rc中传入了--start-system-server参数
                    startSystemServer = true;
                } else if (argv[i].startsWith(ABI_LIST_ARG)) {
                    abiList = argv[i].substring(ABI_LIST_ARG.length());
                } 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]);
                }
            }
            ........
            registerZygoteSocket(socketName); // 调用registerZygoteSocket函数创建一个socket接口,用来和ActivityManagerService通讯
            ........
            if (startSystemServer) {
                startSystemServer(abiList, socketName); // 调用startSystemServer函数来启动SystemServer组件
            }
            // 调用runSelectLoopMode函数进入一个无限循环,在前面创建的socket接口上等待ActivityManagerService请求创建新的应用程序进程
            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;
        }
    }
    ........
    private static void runSelectLoop(String abiList) throws MethodAndArgsCaller {
        ........
        int loopCount = GC_LOOP_COUNT;
        while (true) { // 进入无限循环
            int index;

            if (loopCount <= 0) {
                gc();
                loopCount = GC_LOOP_COUNT;
            } else {
                loopCount--;
            }

            try {
                fdArray = fds.toArray(fdArray);
                index = selectReadable(fdArray); //等待ActivityManagerService来连接这个Socket
            } catch (IOException ex) {
                throw new RuntimeException("Error in select()", ex);
            }

            if (index < 0) {
                throw new RuntimeException("Error in select()");
            } else if (index == 0) {
                ........
            } else {
                boolean done;
                done = peers.get(index).runOnce(); // 调用ZygoteConnection.runOnce函数来创建新的应用程序
                ........
            }
        }
    }
    ........
}

4.RuntimeInit函数
public class RuntimeInit {
    ........
    private static final native void nativeZygoteInit();//实现在frameworks/base/core/jni/AndroidRuntime.cpp文件中
    ........
    public static final void zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
            throws ZygoteInit.MethodAndArgsCaller {
        if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting application from zygote");

        redirectLogStreams();

        commonInit();
        nativeZygoteInit();// 调用zygoteInitNative函数来执行一个Binder进程间通信机制的初始化工作,这个工作完成之后,这个进程中的Binder对象就可以方便地进行进程间通信了

        applicationInit(targetSdkVersion, argv, classLoader); //调用上面传进来的com.android.server.SystemServer类的main函数
    }
    ........
}

5.环境变量ANDROID_SOCKET_zygote的值的由来
系统启动脚本文件system/core/rootdir/init.rc是由源代码位于system/core/init/init.c文件的init进程来解释执行的
service_start函数来解释init.rc文件中的service命令的
void service_start(struct service *svc, const char *dynamic_args)
{
    struct stat s;
    pid_t pid;
    ........
    pid = fork();
    if (pid == 0) {
        struct socketinfo *si;
        struct svcenvinfo *ei;
        ........
        for (ei = svc->envvars; ei; ei = ei->next)
            add_environment(ei->name, ei->value);

        for (si = svc->sockets; si; si = si->next) {
            int socket_type = (
                    !strcmp(si->type, "stream") ? SOCK_STREAM :
                        (!strcmp(si->type, "dgram") ? SOCK_DGRAM : SOCK_SEQPACKET));
            int s = create_socket(si->name, socket_type,
                                  si->perm, si->uid, si->gid, si->socketcon ?: scon);
            if (s >= 0) {
                publish_socket(si->name, s);// 通过这个函数来将得到的文件描述符写入到环境变量中去
            }
        }
     }
     ........
}
........
static void publish_socket(const char *name, int fd)
{
    char key[64] = ANDROID_SOCKET_ENV_PREFIX; //在system/core/include/cutils/sockets.h定义
    char val[64];

    strlcpy(key + sizeof(ANDROID_SOCKET_ENV_PREFIX) - 1, name, sizeof(key) - sizeof(ANDROID_SOCKET_ENV_PREFIX));
    snprintf(val, sizeof(val), "%d", fd);
    add_environment(key, val); // 写入系统属性

    /* make sure we don't close-on-exec */
    fcntl(fd, F_SETFD, 0);
}

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/从前慢现在也慢/article/detail/227885
推荐阅读
相关标签
  

闽ICP备14008679号