Zygote进程启动流程

博客同步至github博客:Zygote进程启动流程

使用到的相关源码:https://github.com/JesusYoung/AndroidResourceCode9.0/tree/master

基于Android 9.0

1、Zygote进程

Zygote是在init进程启动时创建的,它又称为孵化器,它可以通过fork(复制进程)的形式来创建应用程序进程和SystemServer进程,并且,Zygote进程在启动的时候会创建DVM或者ART,因此通过fork而创建的应用程序进程和SystemServer进程可以在内部获取一个DVM或者ART的实例副本;

2、Zygote进程启动流程

2.1、Init进程调用

2.1.1、解析配置参数

Init进程启动之后,解析init.rc配置文件,执行其配置,其中有启动Zygote进程的参数配置,在app_main.cpp的main()方法中,先解析参数,例如在前面解析.rc文件时添加的参数“–zygote、----start-system-server”等,初始化各种标识位;

int main(int argc, char* const argv[]) {
	...
  ++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) != 0) {
      className.setTo(arg);
      break;
    } else {
      --i;
      break;
    }
  }
  ...
}

2.1.2、启动Dalvik虚拟机

接着判断className是否为空,在Zygote模式下,调用maybeCreateDalvikCache()函数创建Dalvik虚拟机缓存,添加启动systemServer的参数标识;

int main(int argc, char* const argv[]) {
	...
	if (!className.isEmpty()) {
    ...
  } else {
    // We're in zygote mode.
    maybeCreateDalvikCache();
    if (startSystemServer) {
      args.add(String8("start-system-server"));
    }
    char prop[PROP_VALUE_MAX];
    if (property_get(ABI_LIST_PROPERTY, prop, NULL) == 0) {
      LOG_ALWAYS_FATAL("app_process: Unable to determine ABI list from property %s.", ABI_LIST_PROPERTY);
      return 11;
    }
    String8 abiFlag("--abi-list=");
    abiFlag.append(prop);
    args.add(abiFlag);
    // In zygote mode, pass all remaining arguments to the zygote main() method.
    // 在Zygote模式下,将剩余的参数全部传递过去
    for (; i < argc; ++i) {
      args.add(String8(argv[i]));
    }
    ...
}

2.2、启动Zygote

2.2.1、创建AppRunTime对象

在main()函数中创建了AppRunTime对象,AppRunTime对象继承自AndroidRunTime类;

int main(int argc, char* const argv[]) {
  ...
  AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
  ...
}

class AppRuntime : public AndroidRuntime {
  public:
  AppRuntime(char* argBlockStart, const size_t argBlockLength)
    : AndroidRuntime(argBlockStart, argBlockLength) , mClass(NULL) {
    }
  ...
}

2.2.2、AppRunTime启动Zygote

随后调用AppRunTime类的start()方法来启动Zygote进程,在前面判断中得知zygote参数为true;

if (zygote) {
  runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
} else if (className) {
  runtime.start("com.android.internal.os.RuntimeInit", args, zygote);
} else {
  ...
}

AppRunTime类继承自AndroidRunTime类,AppRunTime类并没有重载start()方法,所以这里执行的是AndroidRunnTime类的start()方法;

2.2.3、注册JNI

首先会初始化一些环境rootDir等,然后会启动虚拟机,调用startReg()函数向虚拟机注册Android Native方法;

拿到前面传入的类名,即com.android.internal.os.ZygoteInit,通过JNI调用其main()方法,因为此处为C代码,而ZygoteInit为Java类,所以调用时需要使用JNI方式去调用,此时,正式从C层进入Java层;

class AppRuntime : public AndroidRuntime {}

void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote) {
  ...
  // 启动虚拟机
  if (startVm(&mJavaVM, &env, zygote) != 0) {
    return;
  }
  ...
  // 向虚拟机注册Android Native方法
  if (startReg(env) < 0) {
    ALOGE("Unable to register all android natives\n");
    return;
  }
  ...
  char* slashClassName = toSlashClassName(className != NULL ? className : "");
  jclass startClass = env->FindClass(slashClassName);
  if (startClass == NULL) {
    ...
  } else {
    // 找到main()方法
    jmethodID startMeth = env->GetStaticMethodID(startClass, "main", "([Ljava/lang/String;)V");
    if (startMeth == NULL) {
      ...
    } else {
      // 调用ZygoteInit类的main()方法
      env->CallStaticVoidMethod(startClass, startMeth, strArray);
      #if 0
      if (env->ExceptionCheck())
        threadExitUncaughtException(env);
      #endif
    }
  }
  ...
}

2.2.4、启动进入Java层Zygote

Zygote进程启动,在ZygoteInit的main()方法中,通过调用ZygoteHooks类的startZygoteNoThreadCreation()函数来抛出异常,标识Zygote进程已经启动;

public static void main(String argv[]) {
  ZygoteServer zygoteServer = new ZygoteServer();
  // Mark zygote start. This ensures that thread creation will throw
  // an error.
  ZygoteHooks.startZygoteNoThreadCreation();
  ...
}

2.3、创建Zygote进程Socket

2.3.1、创建服务端socket

在ZygoteInit的main()函数中,创建了ZygoteServer对象,作为Zygote进程的socket通信的服务端,名为zygote,用来接收SystemServer进程向Zygote进程发来的请求,例如AMS向Zygote进程请求创建新应用等,接着调用runSelectLoop()来等待SystemServer进程发来的请求;

public static void main(String argv[]) {
  ZygoteServer zygoteServer = new ZygoteServer();
  ...
  try {
    ...
    zygoteServer.registerServerSocketFromEnv(socketName);
    ...
    caller = zygoteServer.runSelectLoop(abiList);
  }
  ...
  if (caller != null) {
    caller.run();
  }
}

// ZygoteServer 
void registerServerSocketFromEnv(String socketName) {
  if (mServerSocket == null) {
    int fileDesc;
    final String fullSocketName = ANDROID_SOCKET_PREFIX + socketName;
    try {
      String env = System.getenv(fullSocketName);
      fileDesc = Integer.parseInt(env);
    } catch (RuntimeException ex) {
      throw new RuntimeException(fullSocketName + " unset or invalid", ex);
    }
    try {
      FileDescriptor fd = new FileDescriptor();
      fd.setInt$(fileDesc);
      mServerSocket = new LocalServerSocket(fd);
      mCloseSocketFd = true;
    } catch (IOException ex) {
      throw new RuntimeException("Error binding to local socket '" + fileDesc + "'", ex);
    }
  }
}

2.3.2、执行客户端请求

轮询客户端Socket消息,当客户端有新消息到来时,创建一个新的连接去执行客户端发来的请求,例如AMS请求创建新的进程;

新建一个peers列表,用于存储每个客户端的连接,将fd数据转存到poolFds中,遍历,当i=0时表示有客户端与服务端连接成功,此时执行acceptCommandPeer()方法拿到新的连接,并将其存入到peers集合中,当i>0时,表示客户端在向服务端传输数据,从peers中拿出与客户端的连接,执行processOneCommand()函数得到一个Runnable对象,如果是fork子进程并且任务不为null则返回该Runnable对象,在main()函数中,如果该对象不为空,就去执行其run()方法;

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;
    }
    ...
    for (int i = pollFds.length - 1; i >= 0; --i) {
      ...
      if (i == 0) {
        ZygoteConnection newPeer = acceptCommandPeer(abiList);
        peers.add(newPeer);
        fds.add(newPeer.getFileDesciptor());
      } else {
        try {
          ZygoteConnection connection = peers.get(i);
          final Runnable command = connection.processOneCommand(this);
          if (mIsForkChild) {
            // We're in the child. We should always have a command to run at this
            // stage if processOneCommand hasn't called "exec".
            if (command == null) {
              throw new IllegalStateException("command == null");
            }
            return command;
          } else {
            // We're in the server - we should never have any commands to run.
            if (command != null) {
              throw new IllegalStateException("command != null");
            }
            // We don't know whether the remote side of the socket was closed or
            // not until we attempt to read from it from processOneCommand. This shows up as
            // a regular POLLIN event in our regular processing loop.
            if (connection.isClosedByPeer()) {
              connection.closeSocket();
              peers.remove(i);
              fds.remove(i);
            }
          }
        }
        ...
      }
    }
  }
}

执行processOneCommand()方法时,创建fork子进程的Runnable对象,如果是在父进程中,则返回null,子进程中则会返回fork子进程的Runnable对象,去执行fork操作,并且清除掉fork过来的父进程中的socket信息;

Runnable processOneCommand(ZygoteServer zygoteServer) {
  ...
  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) {
      // in child
      zygoteServer.setForkChild();
      zygoteServer.closeServerSocket();
      IoUtils.closeQuietly(serverPipeFd);
      serverPipeFd = null;
      return handleChildProc(parsedArgs, descriptors, childPipeFd, parsedArgs.startChildZygote);
    } else {
      // In the parent. A pid < 0 indicates a failure and will be handled in
      // handleParentProc.
      IoUtils.closeQuietly(childPipeFd);
      childPipeFd = null;
      handleParentProc(pid, descriptors, serverPipeFd);
      return null;
    }
    ...
}

2.4、启动SystemServer

Zygote进程启动后,执行ZygoteInit类的main()方法,启动会调用forkSystemServer()方法去通过fork自身的方式去创建SystemServer进程;

public static void main(String argv[]) {
	...
  try {
  	...
    if (startSystemServer) {
      Runnable r = forkSystemServer(abiList, socketName, zygoteServer);
      // {@code r == null} in the parent (zygote) process, and {@code r != null} in the
      // child (system_server) process.
      if (r != null) {
        r.run();
        return;
      }
    }
    ...
  }
  ...
}
发布了32 篇原创文章 · 获赞 14 · 访问量 6万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章