Android 中Zygote创建APP进程

《Android 系统源代码情景分析》,博客
AOSP Version:2.3

  • 每当AMS需要创建新的APP进程来启动Activity这些组件时,它会调用ActivityManagerService.中的startProcessLocked()Zygote发送一个创建APP进程的请求.
public final class ActivityManagerService extends ActivityManagerNative implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
    private final void startProcessLocked(ProcessRecord app,String hostingType, String hostingNameStr) {
        ...
        try {
            //获取APP进程的用户id
            int uid = app.info.uid;
            int[] gids = null;
            try {
                //获取APP进程的用户组id
                gids = mContext.getPackageManager().getPackageGids(app.info.packageName);
            } catch (PackageManager.NameNotFoundException e) {
                Slog.w(TAG, "Unable to retrieve gids", e);
            }
            ...
            // 创建APP进程
            // "android.app.ActivityThread":指定应用程序入口函数在ActivityThread类中
            int pid = Process.start("android.app.ActivityThread",
                    mSimpleProcessManagement ? app.processName : null, uid, uid,
                    gids, debugFlags, null);
            ...
            // Zygote创建的APP进程的pid被保存到该进程对应的ProcessRecord对象的pid变量中
            app.pid = pid;
            ...
        }
    }
}
  • 发送Socket消息给Zygote
public class Process {
    public static final int start(final String processClass,
                                  final String niceName,
                                  int uid, int gid, int[] gids,
                                  int debugFlags,
                                  String[] zygoteArgs)
    {
        // supportsProcesses():判断系统是否支持Binder通信
        if (supportsProcesses()) {
            try {
                // 请求Zygote创建APP进程
                return startViaZygote(processClass, niceName, uid, gid, gids,
                        debugFlags, zygoteArgs);
            } catch (ZygoteStartFailedEx ex) {
               ...
            }
        } ...
    }
    
    private static int startViaZygote(final String processClass,
                                  final String niceName,
                                  final int uid, final int gid,
                                  final int[] gids,
                                  int debugFlags,
                                  String[] extraArgs)
                                  throws ZygoteStartFailedEx {
        int pid;
    
        synchronized(Process.class) {
            ArrayList<String> argsForZygote = new ArrayList<String>();
            // --runtime-init 它表示要在新的进程中初始化运行时库以及启动一个Binder线程池
            argsForZygote.add("--runtime-init"); 
            argsForZygote.add("--setuid=" + uid);
            argsForZygote.add("--setgid=" + gid);
            ...
            // 发送请求信息
            pid = zygoteSendArgsAndGetPid(argsForZygote);
        }
        ...
        return pid;
    }
    
    private static int zygoteSendArgsAndGetPid(ArrayList<String> args) throws ZygoteStartFailedEx {
        int pid;
        // 先看下这个方法
        // 建立Socket客户端,并且让客户端与Zygote进程中的Socket服务端进行链接.
        // 链接成功了就可以向Socket服务端发送创建APP进程信息.
        openZygoteSocketIfNeeded();
        try {
            // 这里就开始向Zygote发送信息了
            sZygoteWriter.write(Integer.toString(args.size()));
            sZygoteWriter.newLine();
            int sz = args.size();
            for (int i = 0; i < sz; i++) {
                String arg = args.get(i);
                if (arg.indexOf('\n') >= 0) {
                    throw new ZygoteStartFailedEx(
                            "embedded newlines not allowed");
                }
                sZygoteWriter.write(arg);
                sZygoteWriter.newLine();
            }
            sZygoteWriter.flush();
            // 获取新创建APP进程的pid,这个pid最终会存入ProcessRecord中的pid变量中.
            pid = sZygoteInputStream.readInt();
            ...
        } catch (IOException ex) {
            ...
        }
        return pid;
    }
    
    private static final String ZYGOTE_SOCKET = "zygote";
    // 创建Socket客户端对象
    private static void openZygoteSocketIfNeeded()  throws ZygoteStartFailedEx {
        int retryCount;
        for (int retry = 0 ; (sZygoteSocket == null) && (retry < (retryCount + 1)) ; retry++ ) {
            ...
            try {
                sZygoteSocket = new LocalSocket();
                // sZygoteSocket对象与名称为"zygote"的地址建立链接,也就是在这里与Zygote进程中的Socket服务端建立了链接
                sZygoteSocket.connect(new LocalSocketAddress(ZYGOTE_SOCKET,LocalSocketAddress.Namespace.RESERVED));
                // 获取Socket客户端的输入流
                sZygoteInputStream = new DataInputStream(sZygoteSocket.getInputStream());
                // 获取Socket客户端的输出流
                sZygoteWriter = new BufferedWriter( new OutputStreamWriter(sZygoteSocket.getOutputStream()),256);
                break;
            } catch (IOException ex) {
                ...
            }
        }
    }
}
  • Zygote接收到消息
public class ZygoteInit {
    public static void main(String argv[]) {
        try {
            // 这里就是注册Socket服务端
            registerZygoteSocket();
            ...
            // 启动SystemServer进程
            startSystemServer();
            // 监听Socket服务端
            runSelectLoopMode();
            closeServerSocket();
        }
    }

    private static final String ANDROID_SOCKET_ENV = "ANDROID_SOCKET_zygote";
    // 注册Socket服务端
    private static void registerZygoteSocket() {
        if (sServerSocket == null) {
            int fileDesc;
            try {
                // 得到Socket的环境变量
                String env = System.getenv(ANDROID_SOCKET_ENV);
                // 将Socket环境变量值转换为文件描述符参数
                fileDesc = Integer.parseInt(env);
            } catch (RuntimeException ex) {
                ...
            }
    
            try {
                // 创建服务器端Socket
                sServerSocket = new LocalServerSocket(createFileDescriptor(fileDesc));
            } catch (IOException ex) {
                ...
            }
        }
    }
    // 对sServerSocket监听
    private static void runSelectLoopMode() throws MethodAndArgsCaller {
        ArrayList<FileDescriptor> fds = new ArrayList();
        ArrayList<ZygoteConnection> peers = new ArrayList();
        FileDescriptor[] fdArray = new FileDescriptor[4];
        fds.add(sServerSocket.getFileDescriptor());
        peers.add(null);
        while (true) {
            ...
            if (index < 0) {
                throw new RuntimeException("Error in select()");
            } else if (index == 0) {
                // 这里是链接成功的处理逻辑
                ZygoteConnection newPeer = acceptCommandPeer();
                peers.add(newPeer);
                fds.add(newPeer.getFileDesciptor());
            } else {
                // 收到创建APP进程消息处理逻辑
                boolean done;
                // 开始创建进程
                done = peers.get(index).runOnce();
                if (done) {
                    peers.remove(index);
                    fds.remove(index);
                }
            }
        }
    }
}
  • 开始fork子进程
class ZygoteConnection {
    boolean runOnce() throws ZygoteInit.MethodAndArgsCaller {
        ...
        int pid;
        try {
            ..
            // forkAndSpecialize()理解
            // 该方法是调用一次,返回两次.它会在Zygote进程中调用一次,在Zygote进程和子进程中各返回一次.
            // 通过返回的进程pid判断当前是走到了Zygote进程中还是APP子进程中.
            // 如果是APP子进程中,最终将会在该进程中调用熟悉的ActivityThread.java中的main().
            pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid,parsedArgs.gids, parsedArgs.debugFlags, rlimits);
        } 
        if (pid == 0) {
            // 处理APP进程
            handleChildProc(parsedArgs, descriptors, newStderr);
            return true;
        } else { 
            return handleParentProc(pid, descriptors, parsedArgs);
        }
    }
    // 处理APP进程
    private void handleChildProc(Arguments parsedArgs, FileDescriptor[] descriptors, PrintStream newStderr) throws ZygoteInit.MethodAndArgsCaller {
         // 在AMS中,启动一个APP进程时候在Process.startViaZygote()设置了argsForZygote.add("--runtime-init"); ,
         // 表示要初始化一个运行时库以及启动一个Binder线程池
         if (parsedArgs.runtimeInit) {
             RuntimeInit.zygoteInit(parsedArgs.remainingArgs);
         } 
    }
}
  • 对fork出的APP进程进行处理
public class RuntimeInit {
    public static final void zygoteInit(String[] argv) throws ZygoteInit.MethodAndArgsCaller {
        ... 
        // 设置时区和键盘布局信息   
        commonInit();
        // 启动Binder线程池
        zygoteInitNative();
        ...
        // 开始调用ActivityThread.java中的main();
        invokeStaticMain(startClass, startArgs);
    }
    
    private static void invokeStaticMain(String className, String[] argv)
            throws ZygoteInit.MethodAndArgsCaller {
        ...    
        Class<?> cl;
        try {
            cl = Class.forName(className);
        } catch (ClassNotFoundException ex) {
            ...
        }
        Method m;
        try {
            // 获取main()
            m = cl.getMethod("main", new Class[] { String[].class });
        }
        ...
        // 这里看起来很奇怪, 其实很好理解
        // [参考博客](https://blog.csdn.net/weixin_34232363/article/details/91429380)
        throw new ZygoteInit.MethodAndArgsCaller(m, argv);
    }
}
  • 清除调用过程的堆栈信息
  1. 最初接收Socket客户端消息并处理是在ZygoteInit.main(),如果RuntimeInit.invokeStaticMain()抛出异常,最终会抛到ZygoteInit.main()中.
public class ZygoteInit {
    public static void main(String argv[]) {
        try {
           ...
        } catch (MethodAndArgsCaller caller) {
            // MethodAndArgsCaller caller: 将RuntimeInit.invokeStaticMain()中抛出的异常捕获到了
            // 看看它的run()
            caller.run();
        } catch (RuntimeException ex) {
            closeServerSocket();
            throw ex;
        }
    }
    public static class MethodAndArgsCaller extends Exception implements Runnable {
        private final Method mMethod;
        private final String[] mArgs;
        public MethodAndArgsCaller(Method method, String[] args) {
            mMethod = method;
            mArgs = args;
        }
        public void run() {
            try {
                // 这里最终将调用ActivityThread.java中的main().
                mMethod.invoke(null, new Object[] { mArgs });
            } 
            ...
        }
    }
}
  • App进程中UI线程进入消息循环
  1. 当APP进程启动之后,就会调用ActivityThread.main(),在这里将会启动UI线程得消息循环.
// ActivityThread.java
public final class ActivityThread {
    public static final void main(String[] args) {
        ...
        // 创建looper对象,设置主线程looper.    
        Looper.prepareMainLooper();
        ...
        // 为该线程得looper开启消息循环监听,这样主线程的Handler机制就开动起来了.
        Looper.loop();
        ...
    }
}
//Looper.java
public class Looper {
    public static final void prepareMainLooper() {
        prepare();// 为当前线程准备新的looper对象,并与当前线程关联.
        setMainLooper(myLooper());// 获取当前线程对应的looper对象,将该looper对象设置为mMainLooper变量值.
        ...
    }
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值