古有女娲造人,今有我zygote造进程!java
Linux天字第一号进程【init】把我带来了这个世界,不甘平凡的我,得有本身的一方天地。因而我自创了本身的一方世界【Java】。虽然有了本身的小天地,但只有本身孤零零一我的,未免太孤独了,得为这个世界添加更多的精彩。但凭我一我的干,岂不累死?二话不说,我用本身做为本体,克隆了一份本身,并命名为【system_server】,而后让他去作一些杂七杂八的事,创造各类各样的进程服务。我呢,就留下一个后世联系个人入口,有须要我孵化后代的事,我再出力,其他时间,都是我happy的时间了~~android
哈哈,YY结束,开始正文!微信
在上一篇文章中,咱们大概清楚了【Zygote】的启动流程,由init进程解析init.rc文件并启动,而后【Zygote】fork出了[system_server]进程后,建立了名为【zygote】的【socket】,并阻塞监听这个【socket】,响应【AMS】的进程建立请求。那具体这部分是怎么实现的呢?如下分两部分进行分析,分别是【AMS】端的建立请求过程和【Zygote】端的响应建立的过程。app
经过【startActivity】启动有用时,最终会调用到【AMS】的【startProcess】,咱们的分析就是从这里开始的。下面先上一张流程图,方便你们有一个整体的流程感。socket
【AMS】的【startProcess】方法实现以下:函数
frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
private ProcessStartResult startProcess(String hostingType, String entryPoint,
ProcessRecord app, int uid, int[] gids, int runtimeFlags, int mountExternal,
String seInfo, String requiredAbi, String instructionSet, String invokeWith,
long startTime) {
...
startResult = Process.start(entryPoint,
app.processName, uid, uid, gids, runtimeFlags, mountExternal,
app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
app.info.dataDir, invokeWith,
new String[] {PROC_START_SEQ_IDENT + app.startSeq});
...
}
复制代码
这个方法比较简单,咱们专一咱们所关心的,直接调用【Process】类的【start】方法:oop
frameworks/base/core/java/android/os/Process.java
public static final ProcessStartResult start(final String processClass,
final String niceName,
int uid, int gid, int[] gids,
int runtimeFlags, int mountExternal,
int targetSdkVersion,
String seInfo,
String abi,
String instructionSet,
String appDataDir,
String invokeWith,
String[] zygoteArgs) {
return zygoteProcess.start(processClass, niceName, uid, gid, gids,
runtimeFlags, mountExternal, targetSdkVersion, seInfo,
abi, instructionSet, appDataDir, invokeWith, zygoteArgs);
}
复制代码
方法很简单,只有一句,经过【zygoteProcess】对象,调用它的start方法,【zygoteProcess】是【ZygoteProcess】类的实例化,这里咱们先看看【zygoteProcess】是怎么被new出来的:ui
frameworks/base/core/java/android/os/ZygoteProcess.java
public static final ZygoteProcess zygoteProcess =
new ZygoteProcess(ZYGOTE_SOCKET, SECONDARY_ZYGOTE_SOCKET);
复制代码
调用【ZygoteProcess】的构造函数,而且传入了两个参数:this
frameworks/base/core/java/android/os/ZygoteProcess.java
public static final String ZYGOTE_SOCKET = "zygote";
public static final String SECONDARY_ZYGOTE_SOCKET = "zygote_secondary";
复制代码
这里很重要,传入两个参数,都是跟socket相关,且名称跟【Zygote】相关。这极可能是在为链接【zygote】这个socket作准备。咱们看看【ZygoteProcess】的构造方法实现:spa
frameworks/base/core/java/android/os/ZygoteProcess.java
public ZygoteProcess(String primarySocket, String secondarySocket) {
this(new LocalSocketAddress(primarySocket, LocalSocketAddress.Namespace.RESERVED),
new LocalSocketAddress(secondarySocket, LocalSocketAddress.Namespace.RESERVED));
}
复制代码
构造方法中调用了【this】方法,其实就是另一个构造方法的调用:
public ZygoteProcess(LocalSocketAddress primarySocket, LocalSocketAddress secondarySocket) {
mSocket = primarySocket;
mSecondarySocket = secondarySocket;
}
复制代码
其实也就是:
mSocket = new LocalSocketAddress(primarySocket, LocalSocketAddress.Namespace.RESERVED);
mSecondarySocket = new LocalSocketAddress(secondarySocket, LocalSocketAddress.Namespace.RESERVED;
复制代码
这样就获取了【zygote】的socket入口,后面会经过这个地址去跟【zygote】通信。
咱们继续看看【ZygoteProcess】的start方法:
frameworks/base/core/java/android/os/ZygoteProcess.java
public final Process.ProcessStartResult start(final String processClass,
final String niceName,
int uid, int gid, int[] gids,
int runtimeFlags, int mountExternal,
int targetSdkVersion,
String seInfo,
String abi,
String instructionSet,
String appDataDir,
String invokeWith,
String[] zygoteArgs) {
try {
return startViaZygote(processClass, niceName, uid, gid, gids,
runtimeFlags, mountExternal, targetSdkVersion, seInfo,
abi, instructionSet, appDataDir, invokeWith, false /* startChildZygote */,
zygoteArgs);
} catch (ZygoteStartFailedEx ex) {
Log.e(LOG_TAG,
"Starting VM process through Zygote failed");
throw new RuntimeException(
"Starting VM process through Zygote failed", ex);
}
}
复制代码
这里注意传入给【startViaZygote】方法的倒数第二个参数,后面会影响到咱们分析代码分支走向,这里传进来的是【false】,表示不启动【子Zygote】。【startViaZygote】方法实现以下:
private Process.ProcessStartResult startViaZygote(final String processClass,
final String niceName,
final int uid, final int gid,
final int[] gids,
int runtimeFlags, int mountExternal,
int targetSdkVersion,
String seInfo,
String abi,
String instructionSet,
String appDataDir,
String invokeWith,
boolean startChildZygote,
String[] extraArgs)
throws ZygoteStartFailedEx {
ArrayList<String> argsForZygote = new ArrayList<String>();
// --runtime-args, --setuid=, --setgid=,
// and --setgroups= must go first
argsForZygote.add("--runtime-args");
argsForZygote.add("--setuid=" + uid);
argsForZygote.add("--setgid=" + gid);
...
synchronized(mLock) {
return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi), argsForZygote);
}
}
复制代码
这个方法主要作了两件事:
1.封装参数。这些参数最终会发给【zygote】,【zygote】就是根据这些参数来建立进程的;
2.调用zygoteSendArgsAndGetResult方法将参数发送数据;具体实现以下:
private static Process.ProcessStartResult zygoteSendArgsAndGetResult(
ZygoteState zygoteState, ArrayList<String> args)
throws ZygoteStartFailedEx {
try {
...
final BufferedWriter writer = zygoteState.writer;
final DataInputStream inputStream = zygoteState.inputStream;
writer.write(Integer.toString(args.size()));
writer.newLine();
for (int i = 0; i < sz; i++) {
String arg = args.get(i);
writer.write(arg);
writer.newLine();
}
...
} catch (IOException ex) {
zygoteState.close();
throw new ZygoteStartFailedEx(ex);
}
}
复制代码
在这个方法中,咱们看到了【write】的操做,开始正式往【zygote】这个socket发具体的CMD指令了,这个操做主要事由【zygoteState】中的【writer】方法实现,而【zygoteState】做为参数被传进来:
zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi), argsForZygote);
复制代码
【zygoteState】是由【openZygoteSocketIfNeeded】建立返回的:
private ZygoteState openZygoteSocketIfNeeded(String abi) throws ZygoteStartFailedEx {
...
try {
primaryZygoteState = ZygoteState.connect(mSocket);
} catch (IOException ioe) {
throw new ZygoteStartFailedEx("Error connecting to primary zygote", ioe);
}
return primaryZygoteState;
...
}
复制代码
这里调用了【ZygoteState】的connect方法,建立了socket链接,传入的mSocket参数就是咱们上文提到的利用名为【zygote】的字符串构建的。
这里完成connect,而后再调用write进行发送指令。到了这里,【AMS】发起进程建立的请求流程就分析完成,下一步看看【Zygote】是如何接收指令并解析command完成进程建立的。
就如开头所说的,【zygote】在fork出【system_server】后,就留下了一个供外界联系本身的入口,那就是socket。因此要想响应外界的进程建立需求, 第一步就是要建立socket节点,而后再等待请求,而后解析指令参数,从而建立进程。看看流程图就明白了:
让咱们从socket建立提及吧,这得回到【ZygoteInit】的main方法中,【zygote】真正启动的起点:
frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
public static void main(String argv[]) {
...
zygoteServer.registerServerSocketFromEnv(socketName);
...
caller = zygoteServer.runSelectLoop(abiList);
if (caller != null) {
caller.run();
}
...
}
复制代码
socket的建立经过【zygoteserver】的【registerServerSocketFromEnv】方法实现,这里传参【socketName】,咱们看看它的具体值:
String socketName = "zygote";
复制代码
这里看来就是要建立一个名为【zygote】的socket了。咱们看看它的实现:
frameworks/base/core/java/com/android/internal/os/ZygoteServer.java
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);
}
}
}
复制代码
果真在这边建立了socket。接下来就是监听这个socket,响应各类请求便可。咱们看看【runSelectLoop】的实现:
frameworks/base/core/java/com/android/internal/os/ZygoteServer.java
Runnable runSelectLoop(String abiList) {
fds.add(mServerSocket.getFileDescriptor());
...
while(true) {
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);
...
catch (Exception e) {
...
} finally {
...
}
}
}
}
}
复制代码
这里看到该方法中将以前建立的socket对应文件描述符添加进来,而后调用系统的poll方法进行监听。这里poll方法的超时时间设置为-1,即若是无相关指令过来,就会一直阻塞。当有指令过来的时候,首先经过i的值来进行判断,若是是0,则表示此时还未赞成客户端的链接请求,须要调用【acceptCommandPeer】方法赞成这次请求,并将该【connection】对应的文件描述符添加到监听的集合中,下次发了数据过来,就能够被监听到,而后调用【processOneCommand】方法进行处理:
frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java
Runnable processOneCommand(ZygoteServer zygoteServer) {
...
try {
//读取AMS发过来的参数
args = readArgumentList();
descriptors = mSocket.getAncillaryFileDescriptors();
} catch (IOException ex) {
throw new IllegalStateException("IOException on command socket", ex);
}
...
//开始解析参数,并保存到parsedArgs中
parsedArgs = new Arguments(args);
...
//根据解析出来的参数fork进程
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;
}
} finally {
IoUtils.closeQuietly(childPipeFd);
IoUtils.closeQuietly(serverPipeFd);
}
}
复制代码
该方法中主要作了四件事:
1.调用【readArgumentList】方法获取客户端发过来的数据;
2.解析参数,并保存到parsedArgs中;
3.根据解析出来的参数fork进程;
4.处理建立出来的子进程;
咱们进入到【handleChildProc】方法中,看看是如何实现的:
private Runnable handleChildProc(Arguments parsedArgs, FileDescriptor[] descriptors,
FileDescriptor pipeFd, boolean isZygote) {
...
closeSocket(); //子进程因为也复制了zygote的socket资源,这里须要进行关闭,子进程并不须要
...
if (!isZygote) {
return ZygoteInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs,
null /* classLoader */);
} else {
return ZygoteInit.childZygoteInit(parsedArgs.targetSdkVersion,
parsedArgs.remainingArgs, null /* classLoader */);
}
...
}
复制代码
这里有个isZygote变量,决定代码走向。这个变量是从【AMS】中一路传递下来的,在上一个章节中有提到,传递下来的值是false,因此这里咱们进入到【zygoteInit】中进行分析:
frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
public static final Runnable zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader) {
if (RuntimeInit.DEBUG) {
Slog.d(RuntimeInit.TAG, "RuntimeInit: Starting application from zygote");
}
...
return RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader);
}
复制代码
调用了【RuntimeInit】类的【applicationInit】方法:
protected static Runnable applicationInit(int targetSdkVersion, String[] argv,
ClassLoader classLoader) {
...
final Arguments args = new Arguments(argv);
// The end of of the RuntimeInit event (see #zygoteInit).
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
// Remaining arguments are passed to the start class's static main
return findStaticMain(args.startClass, args.startArgs, classLoader);
}
复制代码
很明显,调用【findStaticMain】获取fork出来的main方法,看看具体实现:
frameworks/base/core/java/com/android/internal/os/RuntimeInit.java
protected static Runnable findStaticMain(String className, String[] argv,
ClassLoader classLoader) {
Class<?> cl;
try {
cl = Class.forName(className, true, classLoader);
} catch (ClassNotFoundException ex) {
throw new RuntimeException(
"Missing class when invoking static main " + className,
ex);
}
Method m;
try {
m = cl.getMethod("main", new Class[] { String[].class });
} catch (NoSuchMethodException ex) {
throw new RuntimeException(
"Missing static main on " + className, ex);
} catch (SecurityException ex) {
throw new RuntimeException(
"Problem getting static main on " + className, ex);
}
int modifiers = m.getModifiers();
if (! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) {
throw new RuntimeException(
"Main method is not public and static on " + className);
}
return new MethodAndArgsCaller(m, argv);
}
复制代码
经过反射获取到对应进程的main方法,而后再将main方法看成参数传给的【MethodAndArgsCaller】的构造函数:
static class MethodAndArgsCaller implements Runnable {
/** method to call */
private final Method mMethod;
/** argument array */
private final String[] mArgs;
public MethodAndArgsCaller(Method method, String[] args) {
mMethod = method;
mArgs = args;
}
public void run() {
try {
mMethod.invoke(null, new Object[] { mArgs });
} catch (IllegalAccessException ex) {
throw new RuntimeException(ex);
} catch (InvocationTargetException ex) {
Throwable cause = ex.getCause();
if (cause instanceof RuntimeException) {
throw (RuntimeException) cause;
} else if (cause instanceof Error) {
throw (Error) cause;
}
throw new RuntimeException(ex);
}
}
}
复制代码
这里的run主要经过【invoke】方法调用进程的main方法。
【MethodAndArgsCaller】方法最终返回一个【Runnable】对象,该对象会被一路返回,最终返回到【ZygoteInit】,由caller拿到:
caller = zygoteServer.runSelectLoop(abiList);
if (caller != null) {
caller.run();
}
复制代码
而后调用【run】方法启动进程。
到了这里,进程正式启动,开始了它的一辈子。只要不作什么犯法的事,就不会被杀。固然,关键是不要做(过于占用内存和CPU资源),否则也会被系统杀死。
写得好累,终于撸完。此时此刻想来瓶快乐肥皂水!!!
我在微信公众号也有写文章,更新比较及时,有兴趣者能够扫描以下二维码,或者微信搜索【Android系统实战开发】,关注有惊喜哦!