美文网首页Android开发Android开发经验谈Android技术知识
Android应用进程的创建 — Activity的启动流程

Android应用进程的创建 — Activity的启动流程

作者: Geekholt | 来源:发表于2020-04-10 15:17 被阅读0次

目录

前言

Android世界的起源 — Zygote我们讲了Android系统的启动过程,了解了Zygote进程的作用,其中最重要的作用就是孵化应用进程,那我们本节就来详细讲讲Zygote是如何孵化应用进程的

注意:本文采用的是API28(Android 9)来进行源码分析

两种启动进程的方式

在上文中我们说了一个结论:

每个应用进程不仅有自己的数据资源和需要执行的代码,还需要用到Android框架中通用的资源和代码,由于这些资源和代码是大部分应用都需要调用到的,并且比较重量级,所以安卓把它们都放在Zygote进程的空间中,而应用进程又是继承于Zygote进程,所以当应用需要的时候就直接到里面去找就行了

是不是会有人有点好奇,应用进程为什么能拿到Zygote进程中的资源呢?进程中的这种“继承”关系(注意这里说的不是java中的继承,只是一个比喻)是如何设计的呢?接下来我们来看一下进程的启动方式

首先创建进程都是通过fork()函数,fork() 函数是一次执行,两次返回。说的更严谨一点是 两个进程对用一个程序的两次执行。当 pid == 0 时,说明现在处于子进程,当 pid > 0 时,说明处于父进程

fork()进程后,接下来会分为两种类型的子进程启动方式

第一种:

pid_t pid = fork();
if(pid == 0){
        //child process
}else{
        //parent process
}

通过这种方式创建的子进程,默认继承了父进程的所有资源,这就是应用进程的启动方式

第二种:

pid_t pid = fork();
if(pid == 0){
        //child process
        execve(path,argv,env);
}else{
        //parent process
}

这种方式在子进程中调用了execve(path,argv,env)函数,会去加载另一个可执行程序,那么子进程所继承的资源都会被清除,这就是Zygote进程的启动方式

path:可执行程序的路径

argvs:附带的参数

env:环境变量

应用进程的启动时机

在应用层当中,我们可以通过startActivity()启动我们应用内部的页面,也可以按照约定的协议跳转到其他的应用的Activity,当我们的应用启动了其他应用的Activity时(不仅仅是Activity,启动四大组件都是同样的道理),也就意味着这个Activity所对应的应用进程也启动了。实际上startActivity()内部并没有直接启动进程的逻辑,Android系统也没有给我们的应用层中暴露启动进程相关的接口,那么这个新的进程是如何被启动的呢?

我们来看一下调用startActivity()后经历了哪些过程:(代码这里就省略了,有兴趣的可以自己跟一下代码)

第一部分:当前进程与ASM进程建立Binder通信,发起startActivity请求

  1. Activity#startActivity()

  2. Activity#startActivityForResult()

  3. Instrumentation#execStartActivity()

  4. Instrumentation#execStartActivitiesAsUser()

  5. ActivityManager.getService().startActivities()getService()会返回IActivityManagerIActivityManager实际上就是跨进程通信AIDL中的Client持有的Server句柄,也就是说,Client可以通过IActivityManager接口向Server发送请求,而这里的Server就是ActivityServiceManager ,因为它继承了 IActivityManager.Stub

第二部分:ASM处理startActivity请求,通过Socket向Zygote进程请求创建应用进程

  1. ActivityServiceManager#startActivities()
  2. ActivityStarter#execute()
  3. ActivityStarter#startActivityMayWait()
  4. ActivityStarter#startActivity()
  5. ActivityStarter#startActivityUnchecked()
  6. ActivityStackSupervisor#resumeFocusedStackTopActivityLocked()
  7. ActivityStack#resumeTopActivityUncheckedLocked()
  8. ActivityStack#resumeTopActivityInnerLocked()
  9. ActivityStackSupervisor#startSpecificActivityLocked()
void startSpecificActivityLocked(ActivityRecord r,
        boolean andResume, boolean checkConfig) {
    ProcessRecord app = mService.getProcessRecordLocked(r.processName,
            r.info.applicationInfo.uid, true);

    getLaunchTimeTracker().setLaunchTime(r);

    if (app != null && app.thread != null) {
        //进程已经启动
        try {
            if ((r.info.flags&ActivityInfo.FLAG_MULTIPROCESS) == 0
                    || !"android".equals(r.info.packageName)) {
                app.addPackage(r.info.packageName, r.info.applicationInfo.longVersionCode,
                        mService.mProcessStats);
            }
            //启动组件,return
            realStartActivityLocked(r, app, andResume, checkConfig);
            return;
        } catch (RemoteException e) {
            Slog.w(TAG, "Exception when starting activity "
                    + r.intent.getComponent().flattenToShortString(), e);
        }
    }
        
    //进程没有启动,去启动进程
    mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
            "activity", r.intent.getComponent(), false, false, true);
}
  1. ActivityManagerService#startProcessLocked(),四种启动组件的方式,startActivitystartServicesendBroadcastContentResolver.query,都会执行到这个方法,这就是AMS请求创建进程的入口
  2. ActivityManagerService#startProcess
  3. Process.start()
  4. ZygoteProcess#start()
  5. ZygoteProcess#startViaZygote()
  6. ZygoteProcess.openZygoteSocketIfNeeded(),打开本地Socket,AMS作为Client
  7. ZygoteProcess.zygoteSendArgsAndGetResult(),通过Socket向Zygote进程发送一个参数列表,然后就进入阻塞状态,直到远程Socket服务端返回新创建的进程pid

第三部分:Zygote处理Socket请求,创建子进程并反射调用ActivityThread

Android世界的起源 — Zygote中我们分析了ZygoteInit.main()函数,这里面会创建一个ZygoteServer,并调用ZygoteServer#runSelectLoop来死循环监听Socket的Client(AMS)发来的消息

  1. ZygoteServer#runSelectLoop
  2. ZygoteConnection#processOneCommand()
  3. Zygote.forkAndSpecialize()
Runnable processOneCommand(ZygoteServer zygoteServer) {
    String args[];
    Arguments parsedArgs = null;
    FileDescriptor[] descriptors;
  
    //....
        
    //fork进程
    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);

    try {
        if (pid == 0) {
            //子进程执行
            zygoteServer.setForkChild();

            zygoteServer.closeServerSocket();
            IoUtils.closeQuietly(serverPipeFd);
            serverPipeFd = null;
                        //进入子进程流程
            //parsedArgs.startClass就是ActivityThread类,是前面AMS通过Socket发送过来的
            return handleChildProc(parsedArgs, descriptors, childPipeFd,
                    parsedArgs.startChildZygote);
        } else {
            //父进程执行
            IoUtils.closeQuietly(childPipeFd);
            childPipeFd = null;
            handleParentProc(pid, descriptors, serverPipeFd);
            return null;
        }
    } finally {
        IoUtils.closeQuietly(childPipeFd);
        IoUtils.closeQuietly(serverPipeFd);
    }
}
  1. ZygoteInite.zygoteInit()
  2. RuntimeInit.applicationInit()
  3. RuntimeInit.findStaticMain(),反射调用ActivityThread

第四部分:进入ActivityThread

ActivityThread,本身不是一个线程,但它管理着应用进程中主线程的执行,在ActivityManager请求时调度和执行ActivityServiceBroadcast和其它操作

  1. ActivityThread.main()
public static void main(String[] args) {
    ......
    //创建主线程的Looper
    Looper.prepareMainLooper();
    //关联AMS
    ActivityThread thread = new ActivityThread();
    thread.attach(false);

    //初始化主线程Handler
    if (sMainThreadHandler == null) {
        sMainThreadHandler = thread.getHandler();
    }

    // 进行主线程消息循环
    Looper.loop();

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

至此,进程创建完毕,并且也有了主线程,剩下的便是启动Activity和关联context等初始化操作了

总结

本文主要为了重点讲解应用进程的创建过程,所以过程中一些细节代码就没有罗列出来,如果对更多的细节感兴趣,这里推荐两篇我觉得写得还不错的文章
https://blog.csdn.net/qq_30993595/article/details/82747738
https://blog.csdn.net/luoshengyang/article/details/6689748

相关文章

网友评论

    本文标题:Android应用进程的创建 — Activity的启动流程

    本文链接:https://www.haomeiwen.com/subject/vtmrmhtx.html