system_server除了在进程刚创建的时候通过/dev/socket/zygote,连接一下zygote 之后,只有在打开apk需要fork 进程时,会再次连接zygote 进程。
system_server 在创建是首次连接zygote, 是因为zygote 进程需要保存system_server的ZygoteConnection对象,为了之后读取system_server 传入参数,加快效率,可以看:
http://blog.youkuaiyun.com/xiaolli/article/details/72834220
###system_server 创建进程
apk 端创建新的进程一般都是通过:activity、service、contentProvider、broadcast这几个,
他们最后都是会走到ams 的startProcessLocked
方法
final ProcessRecord startProcessLocked(String processName, ApplicationInfo info,
boolean knownToBeDead, int intentFlags, String hostingType, ComponentName hostingName,
boolean allowWhileBooting, boolean isolated, int isolatedUid, boolean keepIfLarge,
String abiOverride, String entryPoint, String[] entryPointArgs, Runnable crashHandler) {
ProcessRecord app = newProcessRecordLocked(info, processName, isolated, isolatedUid);
startProcessLocked( app, hostingType, hostingNameStr, abiOverride, entryPoint, entryPointArgs);
return app.pid != 0 ? app :null;
}
private final void startProcessLocked(ProcessRecord app, String hostingType,
String hostingNameStr, String abiOverride, String entryPoint, String[] entryPointArgs) {
Process.ProcessStartResult startResult = Process.start(entryPoint, app.processName, uid, uid, gids, debugFlags, mountExternal,
app.info.targetSdkVersion, app.info.seinfo, requiredAbi, instructionSet, app.info.dataDir, entryPointArgs);
}
在startProcessLocked
方法内会去调用Process.start
方法去fork进程,并将结果返回,
entryPoint
fork进程的入口类,一般为android.app.ActivityThread
,好像只有通过startIsolatedProcess 方法才可以指定为其他的类调用方式为:
LocalServices.getService(ActivityManagerInternal.class).startIsolatedProcess(***)
app.processName
fork 进程的进程名
entryPointArgs
入口类的,参数
Process.start
方法:
public static final ProcessStartResult start(final String processClass, final String niceName,int uid, int gid, int[] gids,int debugFlags, int mountExternal, int targetSdkVersion, String seInfo, String abi, String instructionSet, String appDataDir,
String[] zygoteArgs) {
return startViaZygote(processClass, niceName, uid, gid, gids,
debugFlags, mountExternal, targetSdkVersion, seInfo,
abi, instructionSet, appDataDir, zygoteArgs );
}
private static ProcessStartResult startViaZygote(final String processClass,final String niceName, final int uid,
final int gid,final int[] gids,int debugFlags, int mountExternal,int targetSdkVersion,String seInfo,String abi,
String instructionSet, String appDataDir, String[] extraArgs) throws ZygoteStartFailedEx {
synchronized(Process.class) {
ArrayList<String> argsForZygote = new ArrayList<String>();
argsForZygote.add("--runtime-args");
argsForZygote.add("--setuid=" + uid);
argsForZygote.add("--setgid=" + gid);
if ((debugFlags & Zygote.DEBUG_ENABLE_JNI_LOGGING) != 0) {
argsForZygote.add("--enable-jni-logging");
}
argsForZygote.add(processClass);
if (extraArgs != null) {
for (String arg : extraArgs) {
argsForZygote.add(arg);
}
}
return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi), argsForZygote);
}
}
由以上代码可知,Process.start
会去调用其自身的 startViaZygote
方法,
在startViaZygote
方法中,会根据参数添加对应的头(类似"–setuid=")后加入argsForZygote 中,以便在zygote 端进行解析。
此处是将 入口类的参数放入了 argsForZygote 最末尾
入口类放入了, 参数之前。
之后调用openZygoteSocketIfNeeded
方法连接zygote
调用zygoteSendArgsAndGetResult
方法将参数通过socket 传给zygote,并获取结果
openZygoteSocketIfNeeded
去连接socket
public static final String ZYGOTE_SOCKET = "zygote";
private static ZygoteState openZygoteSocketIfNeeded(String abi) throws ZygoteStartFailedEx {
primaryZygoteState = ZygoteState.connect(ZYGOTE_SOCKET);
return primaryZygoteState;
}
zygoteSendArgsAndGetResult
去发送参数,并等待获取结果
private static ProcessStartResult zygoteSendArgsAndGetResult(ZygoteState zygoteState, ArrayList<String> args)throws ZygoteStartFailedEx {
final BufferedWriter writer = zygoteState.writer;
final DataInputStream inputStream = zygoteState.inputStream;
//将数据写入socket 对应的流中
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();
}
writer.flush();
//等待socket那端,并将结果回传过来。
ProcessStartResult result = new ProcessStartResult();
result.pid = inputStream.readInt();
result.usingWrapper = inputStream.readBoolean();
return result;
}
之后就会走到zygote,去进行后续的操作,
###Zygote fork 进程
在Process.java 方法中连接/dev/socket/zygote,并传数据给此socket,那么他的服务端,会接收到数据进行后续操作
ZygoteInit.java 类中
private static void runSelectLoop(String abiList) throws MethodAndArgsCaller {
while (true) {
Os.poll(pollFds, -1); //等待有人连接 /dev/socket/zygote
if (i == 0) {
//system_server进程在创建时第一次与Zygote 连接,将system_server 端的ZygoteConnection 对象存储下来。
} else {
//后续ams 中需要fork 进程时,会调用system_server进程的ZygoteConnection类的 runOnce 方法,读取参数,fork进程,进行后续操作
boolean done = peers.get(i).runOnce();
}
}
}
ZygoteConnection.java
boolean runOnce() throws ZygoteInit.MethodAndArgsCaller {
String args[];
Arguments parsedArgs = null;
FileDescriptor[] descriptors;
//获取ams 中传入的参数
args = readArgumentList();
descriptors = mSocket.getAncillaryFileDescriptors();
int pid = -1;
FileDescriptor childPipeFd = null;
FileDescriptor serverPipeFd = null;
try {
//解析ams 中传入的参数,并将解析结果赋值给Arguments 对象
parsedArgs = new Arguments(args);
FileDescriptor fd = mSocket.getFileDescriptor();
//去fork,apk进程
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) {}
try {
if (pid == 0) {
// in child
IoUtils.closeQuietly(serverPipeFd);
serverPipeFd = null;
//如果是fork 出来的进程,在handleChildProc 中进行后续操作,加载入口类,****
handleChildProc(parsedArgs, descriptors, childPipeFd, newStderr);
return true;
} else {
//如果是zygote进程,在handleParentProc 方法中将结果 通过socket 传给ams,
return handleParentProc(pid, descriptors, serverPipeFd, parsedArgs);
}
}
}
handleParentProc
的操作比较简单,将创建进程的pid传输给了 ams,之后ams那端将不再等待,会获取传输经过,并将ProcessStartResult 返回
private static ProcessStartResult zygoteSendArgsAndGetResult
******
ProcessStartResult result = new ProcessStartResult();
//获取zygote 传过来的pid,赋值给ProcessStartResult,然后将对象返回
result.pid = inputStream.readInt();
result.usingWrapper = inputStream.readBoolean();
return result;
}
handleChildProc
方法的执行,是在新的进程中,此进程即作为apk的运行进程:
private void handleChildProc(Arguments parsedArgs, FileDescriptor[] descriptors, FileDescriptor pipeFd, PrintStream newStderr){
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 */);
}
}
}
在此handleChildProc
方法中,一般都走的是RuntimeInit.zygoteInit,好像很少走 WrapperInit.execApplication
parsedArgs.remainingArgs: String 数组,
数组的第0个元素为 入口类,
其他的元素为 入口类的 参数。
对应Process.startViaZygote
中写入时的情景。
在之后会在 RuntimeInit.zygoteInit
中进行一系列的调用,最后会去反射调用入口类的 main 方法,并将参数传入。
public static final void zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
throws ZygoteInit.MethodAndArgsCaller {
//从定向log,将System.out、System.err,从定向到Android log 中
redirectLogStreams();
//设置默认的异常处理函数,当进程异常crash时,会走UncaughtHandler的uncaughtException 方法。
commonInit();
nativeZygoteInit();
//反射调用入口类的main方法并将参数传入。
applicationInit(targetSdkVersion, argv, classLoader);
}
private static void applicationInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
final Arguments args = new Arguments(argv);
invokeStaticMain(args.startClass, args.startArgs, classLoader);
}
//获取入口类的class,与其方法 method, 将其与参数赋值给 ZygoteInit.MethodAndArgsCaller ,然后将异常抛出去
private static void invokeStaticMain(String className, String[] argv, ClassLoader classLoader){
Class<?> cl = Class.forName(className, true, classLoader);
Method m = cl.getMethod("main", new Class[] { String[].class });
throw new ZygoteInit.MethodAndArgsCaller(m, argv);
}
在invokeStaticMain 方法中,获取到入口的类对象,与main 方法对象,然后构造出一个异常类,之后将异常类抛了出去,此异常会在ZygoteInit.java
中被捕获:
public static void main(String argv[]) {
String socketName = "zygote";
try {
runSelectLoop(abiList);
} catch (MethodAndArgsCaller caller) {
caller.run(); //此处捕获到异常,会反射调用MethodAndArgsCaller内部参数标识入口类。
}
}
public static class MethodAndArgsCaller extends Exception implements Runnable {
private final Method mMethod; //入口类的main 方法
private final String[] mArgs; //入口类的参数
//在invokeStaticMain 赋值
public MethodAndArgsCaller(Method method, String[] args) {
mMethod = method;
mArgs = args;
}
//在ZygoteInit 中,捕获异常并调用
public void run() {
try{
mMethod.invoke(null, new Object[] { mArgs }); //到此就在新进程中执行 android.app.ActivityThread 的main 方法。
} catch (InvocationTargetException ex) {
throw new RuntimeException(ex);
}
}
} =