文章目录

  • 1. Android系统启动流程图
  • 2. fork过程的流程图和调用堆栈
  • 3. Zygote fork过程源码跟踪
  • 4. fork成功之后ActivityThread及后续
  • 5. 小结

上一篇我们对Launcher启动的过程做了一个跟踪,跟踪到AMS通过socket向Zygote请求fork新进程之后就停止追踪了,现在我们单独写一篇,接着上一篇,当然也不仅仅是针对Launcher,对进程的fork过程做一个跟踪和了解

1. Android系统启动流程图

2. fork过程的流程图和调用堆栈

由于Zygote进程在启动时会创建Java虚拟机,因此通过fork而创建的Launcher程序进程可以在内部获取一个Java虚拟机的实例拷贝。fork采用copy-on-write机制,有些类如果不做改变,甚至都不用复制,子进程可以和父进程共享这部分数据,从而省去不少内存的占用

fork过程的架构流程如下图所示:

Zygote的调用栈关系如下图所示:

3. Zygote fork过程源码跟踪

Zygote先fork出SystemServer进程,接着进入循环等待,用来接收Socket发来的消息,用来fork出其他应用进程,比如Launcher

public static void main(String argv[]) {...Runnable caller;....if (startSystemServer) {//Zygote Fork出的第一个进程 SystmeServerRunnable r = forkSystemServer(abiList, zygoteSocketName, zygoteServer);if (r != null) {r.run();return;}}...//循环等待fork出其他的应用进程,比如Launcher//最终通过调用processOneCommand()来进行进程的处理caller = zygoteServer.runSelectLoop(abiList);...if (caller != null) {caller.run(); //执行返回的Runnable对象,进入子进程}
}// ZygoteServer::runSelectLoop -> ZygoteConnection::processOneCommand

循环等待接收到消息后,调用processOneCommand处理:

Runnable processOneCommand(ZygoteServer zygoteServer) {int pid = -1;...//fork子进程,得到一个新的pid//fork子进程,采用copy on write方式,这里执行一次,会返回两次//pid=0 表示Zygote fork子进程成功//pid > 0 表示子进程的真正的PIDpid = Zygote.forkAndSpecialize(parsedArgs.mUid, parsedArgs.mGid, parsedArgs.mGids,parsedArgs.mRuntimeFlags, rlimits, parsedArgs.mMountExternal, parsedArgs.mSeInfo,parsedArgs.mNiceName, fdsToClose, fdsToIgnore, parsedArgs.mStartChildZygote,parsedArgs.mInstructionSet, parsedArgs.mAppDataDir, parsedArgs.mTargetSdkVersion);...if (pid == 0) {// in child, fork成功,第一次返回的pid = 0...return handleChildProc(parsedArgs, descriptors, childPipeFd,parsedArgs.mStartChildZygote);} else {//in parent...childPipeFd = null;handleParentProc(pid, descriptors, serverPipeFd);return null;}
}

pid为0表示fork成功,但此pid并不是fork出的子进程真正的pid,仅表示fork成功与否的标志。接下来看fork成功后执行的handleChildProc方法:

private Runnable handleChildProc(ZygoteArguments parsedArgs, FileDescriptor[] descriptors,FileDescriptor pipeFd, boolean isZygote) {...if (parsedArgs.mInvokeWith != null) {...throw new IllegalStateException("WrapperInit.execApplication unexpectedly returned");} else {if (!isZygote) {// App进程将会调用到这里,执行目标类的main()方法return ZygoteInit.zygoteInit(parsedArgs.mTargetSdkVersion,parsedArgs.mRemainingArgs, null /* classLoader */);} else {return ZygoteInit.childZygoteInit(parsedArgs.mTargetSdkVersion,parsedArgs.mRemainingArgs, null /* classLoader */);}}
}

ZygoteInit.zygoteInit如下:

public static final Runnable zygoteInit(int targetSdkVersion, String[] argv,ClassLoader classLoader) {RuntimeInit.commonInit(); //初始化运行环境ZygoteInit.nativeZygoteInit(); //启动Binder线程池//调用程序入口函数return RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader);
}

在之前讲launcher启动流程时,有讲过,在ZygoteProcess::attemptZygoteSendArgsAndGetResult方法中,Socket连接Zygote进程时,会把之前组装的msg发给Zygote,包括前面的processClass =“android.app.ActivityThread”。而接下来的RuntimeInit.applicationInit会把之前传来的"android.app.ActivityThread" 传递给findStaticMain:

protected static Runnable applicationInit(int targetSdkVersion, String[] argv,ClassLoader classLoader) {...// startClass: 如果AMS通过socket传递过来的是 ActivityThreadreturn findStaticMain(args.startClass, args.startArgs, classLoader);
}

通过反射,拿到ActivityThread的main()方法:

protected static Runnable findStaticMain(String className, String[] argv,ClassLoader classLoader) {Class<?> cl;try {cl = Class.forName(className, true, classLoader);} catch (ClassNotFoundException ex) {throw new RuntimeException("Missing class when invoking static main " + className,ex);}Method m;try {m = cl.getMethod("main", new Class[] { String[].class });} catch (NoSuchMethodException ex) {throw new RuntimeException("Missing static main on " + className, ex);} catch (SecurityException ex) {throw new RuntimeException("Problem getting static main on " + className, ex);}int modifiers = m.getModifiers();if (! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) {throw new RuntimeException("Main method is not public and static on " + className);}return new MethodAndArgsCaller(m, argv);
}

把反射得来的ActivityThread main()入口返回给ZygoteInit的main,通过caller.run()进行调用:

static class MethodAndArgsCaller implements Runnable {/** method to call */private final Method mMethod;/** argument array */private final String[] mArgs;public MethodAndArgsCaller(Method method, String[] args) {mMethod = method;mArgs = args;}//调用ActivityThread的main()public void run() {try {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);}}
}
4. fork成功之后ActivityThread及后续

从上面分析可知,Zygote fork出了应用的进程,并把接下来的应用启动任务交给了ActivityThread来进行,接下来我们就从ActivityThread main()来分析应用的创建过程(以Launcher为例)

调用方法堆栈如下:

主线程处理, 创建ActivityThread对象,调用attach进行处理,最终进入Looper循环:

public static void main(String[] args) {// 安装选择性的系统调用拦截AndroidOs.install();...//主线程处理Looper.prepareMainLooper();...//之前SystemServer调用attach传入的是true,这里到应用进程传入false就行ActivityThread thread = new ActivityThread();thread.attach(false, startSeq);...//一直循环,如果退出,说明程序关闭Looper.loop();throw new RuntimeException("Main thread loop unexpectedly exited");
}

调用ActivityThread的attach进行处理:

private void attach(boolean system, long startSeq) {sCurrentActivityThread = this;mSystemThread = system;if (!system) {//应用进程启动,走该流程...RuntimeInit.setApplicationObject(mAppThread.asBinder());//获取AMS的本地代理类final IActivityManager mgr = ActivityManager.getService();try {//通过Binder调用AMS的attachApplication方法mgr.attachApplication(mAppThread, startSeq);} catch (RemoteException ex) {throw ex.rethrowFromSystemServer();}...} else {//通过system_server启动ActivityThread对象...}// 为 ViewRootImpl 设置配置更新回调,// 当系统资源配置(如:系统字体)发生变化时,通知系统配置发生变化ViewRootImpl.ConfigChangedCallback configChangedCallback= (Configuration globalConfig) -> {synchronized (mResourcesManager) {...}};ViewRootImpl.addConfigCallback(configChangedCallback);
}

清除一些无用的记录,最终调用ActivityStackSupervisor.java的 realStartActivityLocked(),进行Activity的启动:

public final void attachApplication(IApplicationThread thread, long startSeq) {synchronized (this) {//通过Binder获取传入的pid信息int callingPid = Binder.getCallingPid();final int callingUid = Binder.getCallingUid();final long origId = Binder.clearCallingIdentity();attachApplicationLocked(thread, callingPid, callingUid, startSeq);Binder.restoreCallingIdentity(origId);}
}private final boolean attachApplicationLocked(IApplicationThread thread,int pid, int callingUid, long startSeq) {...//如果当前的Application记录仍然依附到之前的进程中,则清理掉if (app.thread != null) {handleAppDiedLocked(app, true, true);}·//mProcessesReady这个变量在AMS的 systemReady 中被赋值为true,//所以这里的normalMode也为trueboolean normalMode = mProcessesReady || isAllowedWhileBooting(app.info);...if (normalMode) {...//调用ATM的attachApplication(),最终层层调用到ActivityStackSupervisor.java的 realStartActivityLocked()didSomething = mAtmInternal.attachApplication(app.getWindowProcessController());...}...return true;
}// ActivityTaskManagerInternal::attachApplication ->
// RootActivityContainer::attachApplication ->
// StackSupervisor::realStartActivityLocked

真正准备去启动Activity,通过clientTransaction.addCallback把LaunchActivityItem的obtain作为回调参数加进去,再调用ClientLifecycleManager.scheduleTransaction()得到LaunchActivityItem的execute()方法进行最终的执行。参考上面的第三阶段的调用栈流程

调用栈如下:

boolean realStartActivityLocked(ActivityRecord r, WindowProcessController proc,boolean andResume, boolean checkConfig) throws RemoteException {// 直到所有的 onPause() 执行结束才会去启动新的 activityif (!mRootActivityContainer.allPausedActivitiesComplete()) {...return false;}try {// Create activity launch transaction.// 添加 LaunchActivityItemfinal ClientTransaction clientTransaction = ClientTransaction.obtain(proc.getThread(), r.appToken);//LaunchActivityItem.obtain(new Intent(r.intent)作为回调参数clientTransaction.addCallback(LaunchActivityItem.obtain(new Intent(r.intent),System.identityHashCode(r), r.info,// TODO: Have this take the merged configuration instead of separate global// and override configs.mergedConfiguration.getGlobalConfiguration(),mergedConfiguration.getOverrideConfiguration(), r.compat,r.launchedFromPackage, task.voiceInteractor, proc.getReportedProcState(),r.icicle, r.persistentState, results, newIntents,dc.isNextTransitionForward(), proc.createProfilerInfoIfNeeded(),r.assistToken));...// 设置生命周期状态final ActivityLifecycleItem lifecycleItem;if (andResume) {lifecycleItem = ResumeActivityItem.obtain(dc.isNextTransitionForward());} else {lifecycleItem = PauseActivityItem.obtain();}clientTransaction.setLifecycleStateRequest(lifecycleItem);// Schedule transaction.// 重点关注:调用 ClientLifecycleManager.scheduleTransaction(),得到上面addCallback的LaunchActivityItem的execute()方法mService.getLifecycleManager().scheduleTransaction(clientTransaction);} catch (RemoteException e) {if (r.launchFailed) {// 第二次启动失败,finish activitystack.requestFinishActivityLocked(r.appToken, Activity.RESULT_CANCELED, null,"2nd-crash", false);return false;}// 第一次失败,重启进程并重试r.launchFailed = true;proc.removeActivity(r);throw e;}
} finally {endDeferResume();
}
...
return true;
}

执行之前realStartActivityLocked()中的 clientTransaction.addCallback

//[TransactionExecutor.java]
public void execute(ClientTransaction transaction) {...// 执行 callBack,参考上面的调用栈,执行回调方法,//最终调用到ActivityThread的handleLaunchActivity()executeCallbacks(transaction);// 执行生命周期状态executeLifecycleState(transaction);mPendingActions.clear();
}

主要干了两件事,第一件:初始化WindowManagerGlobal;第二件:调用performLaunchActivity方法

//[ActivityThread.java]
public Activity handleLaunchActivity(ActivityClientRecord r,PendingTransactionActions pendingActions, Intent customIntent) {...//初始化WindowManagerGlobalWindowManagerGlobal.initialize();...//调用performLaunchActivity,来处理Activityfinal Activity a = performLaunchActivity(r, customIntent);...return a;
}

获取ComponentName、Context,反射创建Activity,设置Activity的一些内容,比如主题等; 最终调用callActivityOnCreate()来执行Activity的onCreate()方法

private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {// 获取 ComponentNameComponentName component = r.intent.getComponent();...// 获取 ContextContextImpl appContext = createBaseContextForActivity(r);Activity activity = null;try {// 反射创建 Activityjava.lang.ClassLoader cl = appContext.getClassLoader();activity = mInstrumentation.newActivity(cl, component.getClassName(), r.intent);StrictMode.incrementExpectedActivityCount(activity.getClass());r.intent.setExtrasClassLoader(cl);r.intent.prepareToEnterProcess();if (r.state != null) {r.state.setClassLoader(cl);}} catch (Exception e) {...}try {// 获取 ApplicationApplication app = r.packageInfo.makeApplication(false, mInstrumentation);if (activity != null) {...//Activity的一些处理activity.attach(appContext, this, getInstrumentation(), r.token,r.ident, app, r.intent, r.activityInfo, title, r.parent,r.embeddedID, r.lastNonConfigurationInstances, config,r.referrer, r.voiceInteractor, window, r.configCallback,r.assistToken);if (customIntent != null) {activity.mIntent = customIntent;}...int theme = r.activityInfo.getThemeResource();if (theme != 0) {// 设置主题activity.setTheme(theme);}activity.mCalled = false;// 执行 onCreate()if (r.isPersistable()) {mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);} else {mInstrumentation.callActivityOnCreate(activity, r.state);}...r.activity = activity;}//当前状态为ON_CREATEr.setState(ON_CREATE);...} catch (SuperNotCalledException e) {throw e;} catch (Exception e) {...}return activity;
}

callActivityOnCreate先执行activity onCreate的预处理,再去调用Activity的onCreate,最终完成Create创建后的内容处理:

public void callActivityOnCreate(Activity activity, Bundle icicle,PersistableBundle persistentState) {prePerformCreate(activity); //activity onCreate的预处理activity.performCreate(icicle, persistentState);//执行onCreate()postPerformCreate(activity); //activity onCreate创建后的一些信息处理
}

performCreate()主要调用Activity的onCreate()

final void performCreate(Bundle icicle, PersistableBundle persistentState) {...if (persistentState != null) {onCreate(icicle, persistentState);} else {onCreate(icicle);}...
}

至此,看到了我们最熟悉的Activity的onCreate(),Launcher的启动完成,Launcher被真正创建起来

5. 小结

看到onCreate()后,进入到我们最熟悉的Activity的入口,Launcher的启动告一段落。整个Android的启动流程,我们也完整的分析完成。

Launcher的启动经过了三个阶段:

第一个阶段:SystemServer完成启动Launcher Activity的调用

第二个阶段:Zygote()进行Launcher进程的Fork操作

第三个阶段:进入ActivityThread的main(),完成最终Launcher的onCreate操作

Zygote如何fork一个进程相关推荐

  1. Linux fork()一个进程内核态的变化

    [前言]用户态的变化,耳熟能详不在赘述.现在支持读时共享,写时复制. 一.内核态的变化 1.fork一个子进程代码 #include <stdio.h> #include <stdl ...

  2. linux 内核 fork,Linux fork()一个进程内核态的变化

    [前言]用户态的变化,耳熟能详不在赘述.现在支持读时共享,写时复制. 一.内核态的变化 1.fork一个子进程代码 #include #include#include int main(int arg ...

  3. 从源码解析-Android中Zygote进程是如何fork一个APP进程的

    zygote进程fork子进程 前言 强烈推荐 进程创建流程 APP启动第三方应用 startActivity startService sendBroadcast ContentResolver.q ...

  4. Android10.0应用进程创建过程以及Zygote的fork流程-[Android取经之路]

    摘要:点击手机桌面图标,例如微信,它是如何启动的呢,让我们从系统源码级来一起分析. 阅读本文大约需要花费1小时. 文章的内容主要还是从源码进行分析,虽然又臭又长,但是如果想要学习Android系统源码 ...

  5. linux一个进程通知另外一个进程,Linux进程通信学习笔记

    一.为什么需要进程通信 1)数据传输 一个进程需要把它的数据发送给另一个进程. 2)资源共享 多个进程之间共享同样的资源. 3)通知事件 一个进程向另外一个进程发送消息,通知它发生了某事件. 4)进程 ...

  6. python fork 守护进程

    # -*-coding:utf-8-*- import sys, os'''将当前进程fork为一个守护进程注意:如果你的守护进程是由inetd启动的,不要这样做!inetd完成了所有需要做的事情,包 ...

  7. linux进程管理fork,Linux -- 进程管理之 fork() 函数

    一个进程调用fork()函数后,系统先给新的进程分配资源,例如存储数据和代码的空间.然后把原来的进程的所有值都复制到新的新进程中,只有少数值与原来的进程的值不同.相当于克隆了一个自己. Test1 f ...

  8. Linux 内核如何描述一个进程?

    哈喽,我是吴同学,继续记录我的学习心得. 一.关于写文章 许多知识,书上或者网络上都有,就算这两个地方都没有,代码里也会有答案.但有时恰恰是 资料太多,反而让人难以检索出有用的信息. 面对同样的资料, ...

  9. python进程池一个进程卡住_python进程池,每个进程都有超时

    您可以使f(n)协同工作,以便它总是在超时内完成(如在GUI/网络事件处理程序中).在 如果不能使其协同工作,则唯一可靠的选择是终止运行函数的进程:import multiprocessing as ...

最新文章

  1. 零基础自学python的app-零基础初学Python,需要装什么软件?
  2. Delphi面向对象学习随笔七:COM
  3. 映射网络驱动器会自动断开的解决方法
  4. 前端学习(1127):递归求数学题2
  5. 2011年4月51CTO壁纸点评活动获奖名单【已结束】
  6. 荣耀Magic2 发布:滑盖全面屏、前后6摄、屏下指纹、麒麟980
  7. 阶段1 语言基础+高级_1-3-Java语言高级_05-异常与多线程_第2节 线程实现方式_14_匿名内部类方式实现线程的创建...
  8. java.util.current_Java基础知识-java.util.concurrent包下常见类的使用
  9. 明日之后哪个服务器人最多_明日之后,末日寻宝活动上线,远星城宝箱位置攻略...
  10. python离线安装环境 解决 ERROR: Could not find a version that satisfies the requirement xxx 以及winError[10061]
  11. markdown下载及基本语法
  12. (附源码)PHP疫情上报管理系统 毕业设计 170948
  13. Matlab之linspace函数
  14. Ignite 架构全面解析
  15. 元界Metaverse清单:你需要知道的一切
  16. java——MP3转wav
  17. 随机从map中获取key值
  18. 【dva】dva使用与实现(一)
  19. python的return详解。
  20. Python线程和进程的了解,多线程多进程

热门文章

  1. SLAM总结(一)- SLAM原理概述与简介
  2. 动态规划之硬币面值组合问题
  3. Linux学习笔记——Nginx安装部署
  4. 心得分享——c语言如何将多个字符串赋值给字符串数组(即c语言如何输入并储存多个字符串)
  5. vue在浏览器端报错:Module not found: Error: Can't resolve 'common/js/util' in 'E:\vue-exercise\sell\src'
  6. 国密SM4加解密SM2签名验签COM组件DLL
  7. 计算机重启无法关机,电脑无法关机或重启是为什么?
  8. python连接MySQL数据库的示例代码
  9. 网上收集的几个花指令
  10. HTML图片和多行文字并列显示