System_server 与/dev/socket/zygote

来源:互联网 发布:中国房地产数据统计 编辑:程序博客网 时间:2024/05/16 05:46

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方法

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);             }        }    }                                                                                                             =