System_server 与/dev/socket/zygote

system_server除了在进程刚创建的时候通过/dev/socket/zygote,连接一下zygote 之后,只有在打开apk需要fork 进程时,会再次连接zygote 进程。
system_server 在创建是首次连接zygote, 是因为zygote 进程需要保存system_server的ZygoteConnection对象,为了之后读取system_server 传入参数,加快效率,可以看:
http://blog.csdn.net/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);
             }
        }
    }                                                                                                             =
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值