android8.1启动过程 zygote进程分析2
Posted we1less
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了android8.1启动过程 zygote进程分析2相关的知识,希望对你有一定的参考价值。
次部分承接上一篇文章https://blog.csdn.net/we1less/article/details/116139142?spm=1001.2014.3001.5501
registerServerSocket(socketName) AOSP/frameworks/base/core/java/com/android/internal/os/ZygoteServer.java
void registerServerSocket(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);
} catch (IOException ex) {
throw new RuntimeException(
"Error binding to local socket '" + fileDesc + "'", ex);
}
}
}
final String fullSocketName = ANDROID_SOCKET_PREFIX + socketName;
【1】 拼接socker名称 ANDROID_SOCKET_zygote
String env = System.getenv(fullSocketName);
【2】得到socket的环境变量的值
mServerSocket = new LocalServerSocket(fd);
【3】创建服务器端socket并将文件操作符作为参数传递进去 在zygote进程将systemserver进程启动后就会在你这个服务器端的socket上等待AMS请求zygote进程来创建新的进程
关于socket这里附上一个文章https://www.cnblogs.com/zijianlu/archive/2013/04/18/3028090.html具体可以参考看看
preload(bootTimingsTraceLog) AOSP/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
static void preload(TimingsTraceLog bootTimingsTraceLog) {
Log.d(TAG, "begin preload");
...
preloadClasses();
...
preloadResources();
...
nativePreloadAppProcessHALs();
...
preloadOpenGL();
...
preloadSharedLibraries();
...
preloadTextResources();
...
warmUpJcaProviders();
...
}
【1】预加载位于/system/etc/preloaded-classes文件中的类
【2】预加载drawble和color的资源信息AOSP/frameworks/base/core/res/res/values/arrays.xml
drawble : preloaded_drawables
color : preloaded_color_state_lists
【3】通过JNI调用,预加载底层相关的资源
【4】预加载OpenGL资源
【5】预加载共享库:"android","compiler_rt","jnigraphics"
【6】预加载文本连接符资源
【7】zygote中,内存共享进程
通过【1】【2】步骤的预加载可以使继承自zygote的进程预加载系统文件从而使得进程启动更快
启动systemserver AOSP/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
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;
}
}
【1】forkSystemServer 父进程分支返回null 子进程分支返回 handleSystemServerProcess并返回回去最终调用了run()方法 关于具体systemserver启动会在后面单独开一篇文章去分析到这里只需要知道启动了systemserver就好
【2】Zygote.forkSystemServer 其内部会调用nativeForkSystemServer方法,这个native方法最终会通过fork()方法创建当前进程的一个子进程 对于fork()方法这里给出一篇文章有兴趣的可以参考看看
https://www.cnblogs.com/coolgestar02/archive/2011/04/28/2032018.html 总之fork函数最终在父进程的返回值是子进程的pid,而在子进程返回的则是0
private static Runnable forkSystemServer(String abiList, String socketName,
ZygoteServer zygoteServer) {
...
/* Request to fork the system server process */
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) {
if (hasSecondZygote(abiList)) {
waitForSecondaryZygote(socketName);
}
zygoteServer.closeServerSocket();
return handleSystemServerProcess(parsedArgs);
}
return null;
}
runSelectLoop(abiList) AOSP/frameworks/base/core/java/com/android/internal/os/ZygoteServer.java
Zygote完成了Java的初始工作后,便调用runSelectLoop来让自己无限循环等待。如果收到子孙后台的请求,它便会醒来为他们工作。
Runnable runSelectLoop(String abiList) {
...
fds.add(mServerSocket.getFileDescriptor());
...
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);
...
}
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 {
try {
ZygoteConnection connection = peers.get(i);
final Runnable command = connection.processOneCommand(this);
...
if (connection.isClosedByPeer()) {
connection.closeSocket();
peers.remove(i);
fds.remove(i);
}
}
} catch (Exception e) {
...
}
}
}
}
}
【1】fds.add(mServerSocket.getFileDescriptor()); fds[0]为mServerSocket,即mServerSocket为位于zygote进程中的socket服务端
【2】Os.poll(pollFds, -1); 查询轮训状态,当pollFdd有事件到来则往下执行,否则阻塞在这里
【3】if (i == 0) { ZygoteConnection newPeer = acceptCommandPeer(abiList); peers.add(newPeer); fds.add(newPeer.getFileDesciptor());
客户端第一次请求服务端,服务端调用accept与客户端建立连接,客户端在zygote以ZygoteConnection对象表示
【4】else { try { ZygoteConnection connection = peers.get(i); final Runnable command = connection.processOneCommand(this);
经过上个if操作后,客户端与服务端已经建立连接,并开始发送数据 peers.get(index) 取得发送数据客户端的 ZygoteConnection 对象 然后调用 processOneCommand(this) 方法来出具具体请求
如果 i==0 表示说明服务端socket已经于客户端连接上了 换句话说就是当前zygote进程已经于AMS连接上了
如果 i!=0 表示AMS向zygote进程发送一个创建应用进程的请求 再调用 processOneCommand(this) 方法fork出一个新的进程
【5】fds.remove(i); 处理完则从fds中移除该文件描述符
processOneCommand() AOSP/frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java
在这里fork出一个子进程返回handleChildProc 父进程执行handleParentProc
pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,
parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,
parsedArgs.niceName, fdsToClose, fdsToIgnore, parsedArgs.instructionSet,
parsedArgs.appDataDir);
try {
if (pid == 0) {
// in child
zygoteServer.setForkChild();
zygoteServer.closeServerSocket();
IoUtils.closeQuietly(serverPipeFd);
serverPipeFd = null;
return handleChildProc(parsedArgs, descriptors, childPipeFd);
} 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;
}
以上是关于android8.1启动过程 zygote进程分析2的主要内容,如果未能解决你的问题,请参考以下文章
Android Binder 应用程序Binder 启动源码分析