Android:应用进程的启动细节

746 阅读2分钟

一、应用进程的启动原理

1.1 什么时候触发应用进程的启动?谁发起的

是在应用组建启动的过程中触发的,比如启动Activity的时候,先判断进程是否启动,没有启动就先去启动进程。它是由AMS向Zygote发送socket请求发起的。

1.2 进程是谁启动的?怎么启动的?

1.2.1 步骤一AMS向Zygote发送请求
 private final void startProcessLocked(ProcessRecord app, String hostingType,
            String hostingNameStr, String abiOverride, String entryPoint, String[] entryPointArgs) {
            //获取要创建应用程序进程的uid
            int uid = app.uid;
            int[] gids = null;
            //应用进程的主线程名称
            if (entryPoint == null) entryPoint = "android.app.ActivityThread";
            //启动应用程序进程
             startResult = Process.start(entryPoint,
                        app.processName, uid, uid, gids, debugFlags, mountExternal,
                        app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
                        app.info.dataDir, invokeWith, entryPointArgs);
                        
        
 @GuardedBy("mLock")
    private ZygoteState openZygoteSocketIfNeeded(String abi) throws ZygoteStartFailedEx {
        
            try {
                primaryZygoteState = ZygoteState.connect(mSocket);
            } catch (IOException ioe) {
                throw new ZygoteStartFailedEx("Error connecting to primary zygote", ioe);
            }
        }

    }
    
    //创建socket 并且去连接zygote的server socket
    public static ZygoteState connect(String socketAddress) throws IOException {
            DataInputStream zygoteInputStream = null;
            BufferedWriter zygoteWriter = null;
            final LocalSocket zygoteSocket = new LocalSocket();

            try {
                zygoteSocket.connect(new LocalSocketAddress(socketAddress,
                        LocalSocketAddress.Namespace.RESERVED));

                zygoteInputStream = new DataInputStream(zygoteSocket.getInputStream());

                zygoteWriter = new BufferedWriter(new OutputStreamWriter(
                        zygoteSocket.getOutputStream()), 256);
            } catch (IOException ex) {
                
            }

     

            return new ZygoteState(zygoteSocket, zygoteInputStream, zygoteWriter,
                    Arrays.asList(abiListString.split(",")));
        }

连接上服务端后,就有请求发过去,之前讲的服务端有个runSelectLoop,一直阻塞等待AMS的请求到达,这不就是到了嘛,进入zygote服务端的创建进程的逻辑。

1.2.2 zygote接收请求并创建应用程序进程
    public static final Runnable zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader) {
        //启动Binder进程
        ZygoteInit.nativeZygoteInit();
        //启动ActivityThread
        return RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader);
    }

使用反射的方式去调用main函数,比如之前的SystemServer中的main ,这里是ActivityThread中的main

 protected static Runnable applicationInit(int targetSdkVersion, String[] argv,
            ClassLoader classLoader) {
        // Remaining arguments are passed to the start class's static main
        return findStaticMain(args.startClass, args.startArgs, classLoader);
    }
 private static Runnable findStaticMain(String className, String[] argv,
            ClassLoader classLoader) {
        Class<?> cl;

        try {
            // className 为ActivityThread
            cl = Class.forName(className, true, classLoader);
        } catch (ClassNotFoundException ex) {
            throw new RuntimeException(
                    "Missing class when invoking static main " + className,
                    ex);
        }

        Method m;
        m = cl.getMethod("main", new Class[] { String[].class });

        return new MethodAndArgsCaller(m, argv);
    }

ActivityThread # main()

    public static void main(String[] args) {
        

        Looper.prepareMainLooper();

        ActivityThread thread = new ActivityThread();
        //
        thread.attach(false);

        if (sMainThreadHandler == null) {
            sMainThreadHandler = thread.getHandler();
        }

        if (false) {
            Looper.myLooper().setMessageLogging(new
                LogPrinter(Log.DEBUG, "ActivityThread"));
        }

        Looper.loop();

        throw new RuntimeException("Main thread loop unexpectedly exited");
    }

这里我重点说说attach(),它的作用是向AMS做汇报,这一步完成后,就标识着应用程序进程创建完毕。

private void attach(boolean system) {
        sCurrentActivityThread = this;
        mSystemThread = system;
      
            final IActivityManager mgr = ActivityManager.getService();
            try {
                mgr.attachApplication(mAppThread);
            } catch (RemoteException ex) {
                throw ex.rethrowFromSystemServer();
            }
           
        
        }

使用IActivityManager将ApplicationThread传递过去,AMS正好是继承IActivityManager.stub

在AMS中启动应用组建的时候都会做如下判断

 if (r != null && r.app != null && r.app.thread != null) {
                        try {
                            r.app.thread.scheduleEnterAnimationComplete(r.appToken);
                        } catch (RemoteException e) {
                        }
                    }

==r.app != null 表示该应用程序进程已经存在,r.app.thread != null则表示该应用程序进程的主线程已经准备就绪== 这就是attach打报告的结果

1.2 应用是怎么启用Binder机制的

  1. 什么时候启动Bider
在Zygote创建应用程序进程后进行初始化的时候 启动binder,因为后序应用程序要和AMS进行通行,所以要提前创建。
  1. 怎么启动Binder
1. 打开Binder驱动 2.映射内存,分配缓冲区 3.注册binder线程 4 bind loop