版权说明:本文为 开开向前冲 原创文章,转载请注明出处;
注:限于作者水平有限,文中有不对的地方还请指教
前一篇Zygote——Native中写到AndroidRuntime.cpp 中的start方法中会使用JNI调用Java层的Zygote——ZygoteInit的main方法,这里从ZygoteInit的main方法开始说起:
frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
1-1. Main
public static void main(String argv[]) {
try {
RuntimeInit.enableDdms();
......
boolean startSystemServer = false;
String socketName = "zygote";
String abiList = null;
for (int i = 1; i < argv.length; i++) { //解析从Zygote-Native传递的数据
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());
} 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.");
}
registerZygoteSocket(socketName);//创建Zygote Socket,用于和AMS 通信
......
preload(); //预加载资源,有兴趣的往下跟
......
gcAndFinalize();
......
if (startSystemServer) {
startSystemServer(abiList, socketName);//启动SystemServer
}
Log.i(TAG, "Accepting command socket connections");
runSelectLoop(abiList);//进入select的循环,用来响应其他应用程序的请求
closeServerSocket(); //关闭Socket
} catch (MethodAndArgsCaller caller) {
caller.run(); //核心调用,故意抛出异常来处理
} catch (RuntimeException ex) {
Log.e(TAG, "Zygote died with exception", ex);
closeServerSocket();
throw ex;
}
}
main方法核心:
1. registerZygoteSocket(socketName);//创建Zygote Socket
2. preload(); //预加载资源
3. startSystemServer(abiList, socketName);//启动SystemServer
4. runSelectLoop(abiList);//进入Select循环,等待子进程的请求
5. caller.run(); //核心调用
1-2. registerZygoteSocket(socketName)
private static final String ANDROID_SOCKET_PREFIX = "ANDROID_SOCKET_";
/**
* Registers a server socket for zygote command connections
*
* @throws RuntimeException when open fails
*/
private static void registerZygoteSocket(String socketName) {
if (sServerSocket == null) {
int fileDesc;
final String fullSocketName = ANDROID_SOCKET_PREFIX + socketName;
//ANDROID_SOCKET_zygote为Key的环境变量
try {
String env = System.getenv(fullSocketName);//获取/system/core/init/init.c中
// service_start创建的以ANDROID_SOCKET_zygote为Key的fd
Log.e("Keiven-Chen-1234",env);//我在开机过程打印Log,这里env 是10
fileDesc = Integer.parseInt(env);
} catch (RuntimeException ex) {
throw new RuntimeException(fullSocketName + " unset or invalid", ex);
}
try {
FileDescriptor fd = new FileDescriptor();
fd.setInt$(fileDesc);
sServerSocket = new LocalServerSocket(fd);
//根据前面创建的fd来创建服务端socket,等待和AMS通信
} catch (IOException ex) {
throw new RuntimeException(
"Error binding to local socket '" + fileDesc + "'", ex);
}
}
}
上述代码中fullSocketName=ANDROID_SOCKET_zygote,System.getenv(fullSocketName)的值从哪里来呢?前文init.rc 语法与解析中有提到init.rc中配置的service的启动过程,在/system/core/init/init.cpp中service_start方法中有:
/system/core/init/init.cpp
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));//判断socket 类型
int s = create_socket(si->name, socket_type,
si->perm, si->uid, si->gid, si->socketcon ?: scon);
//创建"/dev/socket/zygote" socket,返回对应的fd
if (s >= 0) {
publish_socket(si->name, s);//发布socket的fd,即将create_socket返回的fd添加到
//以"ANDROID_SOCKET_"为前缀的环境变量;
//Zygote的socket的key 为ANDROID_SOCKET_zygote,也是在这创建的;
}
}
/system/core/init/init.cpp
#define ANDROID_SOCKET_ENV_PREFIX "ANDROID_SOCKET_"
static void publish_socket(const char *name, int fd)
{
char key[64] = ANDROID_SOCKET_ENV_PREFIX;
char val[64];
strlcpy(key + sizeof(ANDROID_SOCKET_ENV_PREFIX) - 1,
name,//socket的名字,比如zygote
sizeof(key) - sizeof(ANDROID_SOCKET_ENV_PREFIX));//拼接ANDROID_SOCKET_xxx的
snprintf(val, sizeof(val), "%d", fd);
add_environment(key, val);//这个fd是create_socket创建的,添加到环境变量
/* make sure we don't close-on-exec */
fcntl(fd, F_SETFD, 0);
}
1-3. preload()
static void preload() {
Log.d(TAG, "begin preload");
preloadClasses(); //加载基础类
preloadResources();//加载资源
preloadOpenGL(); //加载OpenGL
preloadSharedLibraries(); //加载共享库
preloadTextResources(); //加载文本所需资源
// Ask the WebViewFactory to do any initialization that must run in the zygote process,
// for memory sharing purposes.
WebViewFactory.prepareWebViewInZygote();//预加载WebView资源
Log.d(TAG, "end preload");
}
1-4. startSystemServer(String abiList, String socketName)
/**
* Prepare the arguments and fork for the system server process.
*/
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",//设置UID,GID
"--setgid=1000",
"--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,
1018,1021,1032,3001,3002,3003,3006,3007",
"--capabilities=" + capabilities + "," + capabilities,
"--nice-name=system_server",//进程名
"--runtime-args",
"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 */
pid = Zygote.forkSystemServer( //Zygote fork出子进程,这里会调到JNI中
//com_android_internal_os_Zygote.cpp中的ForkAndSpecializeCommon,最终调用fork()创建SystemServer进程
parsedArgs.gids,
parsedArgs.debugFlags,
null,
parsedArgs.permittedCapabilities,
parsedArgs.effectiveCapabilities);
} catch (IllegalArgumentException ex) {
throw new RuntimeException(ex);
}
/* For child process */
if (pid == 0) {//PID==0 代表子进程
if (hasSecondZygote(abiList)) {
waitForSecondaryZygote(socketName);
}
handleSystemServerProcess(parsedArgs);//处理systemserver
}
return true;
}
1-5. runSelectLoop
循环监听Socket,等待处理AMS关于启动应用程序的请求数据;
/**
* Runs the zygote process's select loop. Accepts new connections as
* they happen, and reads commands from connections one spawn-request's
* worth at a time.
*
* @throws MethodAndArgsCaller in a child process when a main() should
* be executed.
*/
private static void runSelectLoop(String abiList) throws MethodAndArgsCaller {
ArrayList fds = new ArrayList();
ArrayList peers = new ArrayList();
fds.add(sServerSocket.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) {
ZygoteConnection newPeer = acceptCommandPeer(abiList);
peers.add(newPeer);
fds.add(newPeer.getFileDesciptor());
} else {
boolean done = peers.get(i).runOnce();//执行子进程的Commands,
//新启动APP也是从这里开始孵化的,后续会有相关说明
if (done) {
peers.remove(i);
fds.remove(i);
}
}
}
}
}
/frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java
/**
* Reads one start command from the command socket. If successful,
* a child is forked and a {@link ZygoteInit.MethodAndArgsCaller}
* exception is thrown in that child while in the parent process,
* the method returns normally. On failure, the child is not
* spawned and messages are printed to the log and stderr. Returns
* a boolean status value indicating whether an end-of-file on the command
* socket has been encountered.
*
* @return false if command socket should continue to be read from, or
* true if an end-of-file has been encountered.
* @throws ZygoteInit.MethodAndArgsCaller trampoline to invoke main()
* method in child process
*/
boolean runOnce() throws ZygoteInit.MethodAndArgsCaller {
String args[];
Arguments parsedArgs = null;
FileDescriptor[] descriptors;
try {
args = readArgumentList();//从Zygote socket中获取参数
descriptors = mSocket.getAncillaryFileDescriptors();
} catch (IOException ex) {
Log.w(TAG, "IOException on command socket " + ex.getMessage());
closeSocket();
return true;
}
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);
applyInvokeWithSecurityPolicy(parsedArgs, peer);
applyDebuggerSystemProperty(parsedArgs);
applyInvokeWithSystemProperty(parsedArgs);
int[][] rlimits = null;
if (parsedArgs.rlimits != null) {
rlimits = parsedArgs.rlimits.toArray(intArray2d);
}
if (parsedArgs.invokeWith != null) {
FileDescriptor[] pipeFds = Os.pipe2(O_CLOEXEC);
childPipeFd = pipeFds[1];
serverPipeFd = pipeFds[0];
Os.fcntlInt(childPipeFd, F_SETFD, 0);
}
/**
* 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;
pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,//真正创建进程
parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,
parsedArgs.niceName, fdsToClose, parsedArgs.instructionSet,
parsedArgs.appDataDir);
} 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) {//pid=0代表子进程
// in child
IoUtils.closeQuietly(serverPipeFd);
serverPipeFd = null;
handleChildProc(parsedArgs, descriptors, childPipeFd, newStderr);//这个方法会抛出
//MethodAndArgsCaller的异常,在main()方法中调用caller.run()处理
// 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);
}
}
readArgumentList()方法从Zygote Socket中读取AMS发送的参数;
forkAndSpecialize这个函数会创建一个进程,而且有两个返回值,一个是在当前进程中返回的,一个是在新创建的进程中返回,即在当前进程的子进程中返回,在当前进程中的返回值就是新创建的子进程的pid值,而在子进程中的返回值是0。这里我只看启动子进程;
handleChildProc
/**
* Handles post-fork setup of child proc, closing sockets as appropriate,
* reopen stdio as appropriate, and ultimately throwing MethodAndArgsCaller
* if successful or returning if failed.
*
* @param parsedArgs non-null; zygote args
* @param descriptors null-ok; new file descriptors for stdio if available.
* @param pipeFd null-ok; pipe for communication back to Zygote.
* @param newStderr null-ok; stream to use for stderr until stdio
* is reopened.
*
* @throws ZygoteInit.MethodAndArgsCaller on success to
* trampoline to code that invokes static main.
*/
private void handleChildProc(Arguments parsedArgs,
FileDescriptor[] descriptors, FileDescriptor pipeFd, PrintStream newStderr)
throws ZygoteInit.MethodAndArgsCaller {
/**
* By the time we get here, the native code has closed the two actual Zygote
* socket connections, and substituted /dev/null in their place. The LocalSocket
* objects still need to be closed properly.
*/
closeSocket();
ZygoteInit.closeServerSocket();//关闭Zygote进程的Zygote,因为子进程不需要
if (descriptors != null) {
try {
Os.dup2(descriptors[0], STDIN_FILENO);
Os.dup2(descriptors[1], STDOUT_FILENO);
Os.dup2(descriptors[2], STDERR_FILENO);
for (FileDescriptor fd: descriptors) {
IoUtils.closeQuietly(fd);
}
newStderr = System.err;
} catch (ErrnoException ex) {
Log.e(TAG, "Error reopening stdio", ex);
}
}
if (parsedArgs.niceName != null) {
Process.setArgV0(parsedArgs.niceName);//设置进程名
}
// End of the postFork event.
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
if (parsedArgs.invokeWith != null) {
WrapperInit.execApplication(parsedArgs.invokeWith,
parsedArgs.niceName, parsedArgs.targetSdkVersion,
VMRuntime.getCurrentInstructionSet(),
pipeFd, parsedArgs.remainingArgs);
} else {
RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion,
parsedArgs.remainingArgs, null /* classLoader */);//最终会调用这里,
//后续在说到SystemServer时也会有这个步骤;后续一起讲
}
}
总结:至此Zygote的流程就完结,Zygote 将进入runSelectLoop无限循环,等待子进程发送过来的消息;此时如果需要启动一个应用,AMS 会向Zygote的socket发送请求,Zygote会在runSelectLoop去去调用 boolean done = peers.get(i).runOnce();完成AMS 请求; ActivityManagerService是通过Process.start函数来创建一个新的进程的,而Process.start函数会首先通过Socket连接到Zygote进程中,最终由Zygote进程来完成创建新的应用程序进程;