探索APP进程的启动流程(二)完结篇

本文详细剖析了Android应用冷启动的全过程,从用户点击图标开始,到系统如何启动Zygote进程并创建新的应用程序进程,最后到应用程序进程与Activity Manager Service (AMS)建立连接。通过流程图和代码分析,清晰地展示了冷启动的关键步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

首先回顾下冷启动的流程图:
冷启动
共有四个步骤:
1.launcher进程通过binder请求ams启动Activity,AMS进程查询内存中是否存在该进程。
2.内存中无相应进程,ams通过socket发送创建进程命令和相关资料到zygote进程。
3.zygote进程收到socket信息后,fork子进程,创建出ActivityThread的进程(目的进程)
4.ActivityThread通过binder把新建的进程信息与AMS进行相关联。
在上一篇博客中探索APP进程的启动流程(一),介绍了从用户点开app到发送指令给zygote进程的过程(步骤1,步骤2)。

再往下就去到Zygote进程(步骤3,步骤4),Zygote接收到初始化进程指令,fork子进程。
(剧透:如果没时间看源码,可以直接去到本文末尾,有 zygote进程等待socket消息和处理的简单模型 图)
frameworks\base\core\java\com\android\internal\os\ZygoteInit.java

public static void main(String argv[]) {
		//ZygoteServer处理有关socket服务端的业务
        ZygoteServer zygoteServer = new ZygoteServer();
        ...
        ///注册Zygote的Socket服务端
        zygoteServer.registerServerSocketFromEnv(socketName);
        ...
          if (startSystemServer) {
                //开启SystemServer
                startSystemServer(abiList, socketName, zygoteServer);
            }
            Log.i(TAG, "Accepting command socket connections");
            //等待客户端请求,
            //在runSelectLoop()里面是while(true),线程堵塞等到客户端的socket发送信息
            zygoteServer.runSelectLoop(abiList);
            //关闭Socket服务端
            zygoteServer.closeServerSocket();
          ...
}

zygoteServer. runSelectLoop(), 进行接收socket客户端信息

\frameworks\base\core\java\com\android\internal\os\ZygoteServer.java

Runnable runSelectLoop(String abiList) {
...
 		ZygoteConnection connection = peers.get(i);
 		//接收到socket客户端信息,processOneCommand进行处理
        final Runnable command = connection.processOneCommand(this);
...
}

\frameworks\base\core\java\com\android\internal\os\ZygoteConnection.java
继续看看processOneCommand()如何处理socket信息

Runnable processOneCommand(ZygoteServer zygoteServer) {
        String args[];
        Arguments parsedArgs = null;
        FileDescriptor[] descriptors;

        try {
            //readArgumentList函数来获取启动应用程序进程的命令参数
            args = readArgumentList();
            ...
            //将readArgumentList函数返回的字符串args封装到Arguments对象parsedArgs中
        	parsedArgs = new Arguments(args);
            ...
            //调用Zygote的forkAndSpecialize函数来创建应用程序进程,
        	//参数为parsedArgs中存储的应用进程启动参数,返回值为pid
       		//forkAndSpecialize函数主要是通过fork当前进程来创建一个子进程(native完成)
	        pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,
	                parsedArgs.runtimeFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,
	                parsedArgs.niceName, fdsToClose, fdsToIgnore, parsedArgs.startChildZygote,
	                parsedArgs.instructionSet, parsedArgs.appDataDir);
            ...
            if (pid == 0) {
                // 如果pid等于0,则说明是现在在新创建的子进程中执行
                // in child
                zygoteServer.setForkChild();

                zygoteServer.closeServerSocket();
                IoUtils.closeQuietly(serverPipeFd);
                serverPipeFd = null;
,
                //调用 handleChildProc 函数来启动这个子进程也就是应用程序进程
                return handleChildProc(parsedArgs, descriptors, childPipeFd,
                        parsedArgs.startChildZygote);
             }
            ...
 }

\frameworks\base\core\java\com\android\internal\os\ZygoteConnection.java
进去handleChildProc()看看

  private Runnable handleChildProc(Arguments parsedArgs, FileDescriptor[] descriptors,
            FileDescriptor pipeFd, boolean isZygote) {
          ...
          //zygoteInit() 来初始化进程
		 return ZygoteInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs,
                        null /* classLoader */);
         ...
	}
            

frameworks\base\core\java\com\android\internal\os\ZygoteInit.java

public static final Runnable zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader) {
     ...
     // 新创建的应用程序进程中创建Binder线程池
        ZygoteInit.nativeZygoteInit();
        //初始化进程入口类ActivityThread
        return RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader);
    }

frameworks\base\core\java\com\android\internal\os\RuntimeInit.java

 protected static Runnable applicationInit(int targetSdkVersion, String[] argv,
            ClassLoader classLoader) {
...
        // args.startClass 为 从AMS的startProcessLocked()传入的参数
	 return findStaticMain(args.startClass, args.startArgs, classLoader);
...
}

再跟进findStaticMain():
frameworks\base\core\java\com\android\internal\os\RuntimeInit.java

 protected static Runnable findStaticMain(String className, String[] argv,
            ClassLoader classLoader) {
        Class<?> cl;
   		 ...
        //根据类加载器,获得Android.app.ActivityThread类
        cl = Class.forName(className, true, classLoader);
        ...
         Method m;
         ...
         //获得ActivityThread.java main()
         m = cl.getMethod("main", new Class[] { String[].class });
         ...
         //把调用ActivityThread. main()的runnable实例返回
        return new MethodAndArgsCaller(m, argv);
}

new MethodAndArgsCaller(m, argv)返回的runnable实例到ZygoteInit类的caller对象。 在ZygoteInit.main()方法中执行caller.run()
frameworks\base\core\java\com\android\internal\os\ZygoteInit.java

public static void main(String argv[]) {
        ZygoteServer zygoteServer = new ZygoteServer();
		...
		// We're in the child process and have exited the select loop. Proceed to execute the
        // command.
        //子进程会离开socket服务端等待信息的循环
        if (caller != null) {
            caller.run();
        }

MethodAndArgsCaller.run()执行了,ActivityThread.main()。
在代码,有:

static class MethodAndArgsCaller implements Runnable {
....
	public void run() {
            try {
            //mMethod为ActivityThread.main()方法。这里调用ActivityThread的main()
                mMethod.invoke(null, new Object[] { mArgs });
            } catch (IllegalAccessException ex) {
                throw new RuntimeException(ex);
            } catch (InvocationTargetException ex) {
                Throwable cause = ex.getCause();
                if (cause instanceof RuntimeException) {
                    throw (RuntimeException) cause;
                } else if (cause instanceof Error) {
                    throw (Error) cause;
                }
                throw new RuntimeException(ex);
            }
        }
....
}

初始化ActivityThread类(进程的入口类)
\frameworks\base\core\java\android\app\ActivityThread.java

//ApplicationThread 为 ActivityThread内部类,是binder服务的服务端
 final ApplicationThread mAppThread = new ApplicationThread();
 
public static void main(String[] args) {
	...
	//初始化进程的主线程 Looper
	Looper.prepareMainLooper();
	...
	//实例化 ActivityThread 对象
	ActivityThread thread = new ActivityThread();
	//在attach()方法里进行请求ams绑定当前新建的进程
    thread.attach(false, startSeq);
	...
	//loop启动
	 Looper.loop();
	...
}

继续跟进attach()
\frameworks\base\core\java\android\app\ActivityThread.java

    private void attach(boolean system, long startSeq) {
    ...
    //获得ActivityManagerService服务
    final IActivityManager mgr = ActivityManager.getService();
    //调用ActivityManagerService.attachApplication(),并传入mAppThread。请求关联进程
    mgr.attachApplication(mAppThread, startSeq);
    ...
    }

zygote进程等待socket消息和处理的简单模型

将上述的代码分析,转成流程图形式:
< zygote进程等待socket消息和处理的简单模型>
在这里插入图片描述

在这两篇文章里,只对进程的创建做分析。对于APP的启动流程,这里先不做细节分析,后续文章再继续简述APP的启动流程。

来到这里,从 新建一个进程 到 把进程与AMS关联的关键步骤已大概分析介绍。如果有其他疑问或有错误地方可以给我留言哦。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值