https://blog.csdn.net/zembers/article/details/48519661
上篇文章分析了b2g进程的基本启动过程,那么nuwa进程是什么东东?Firefox os创建新进程又是如何发生的?
nuwa进程类似于android内的zygote进程,需要启动一个应用时,nuwa会预先fork一个进程出来,该进程与父进程(nuwa)共享了某些资源(代码段,已打开文件描述符等),之后会加载应用的html,变成需要启动的应用。
使用nuwa预先创建的空壳进程,能够加快应用启动速度。
以下分析nuwa进程的创建以及初始化:
main() (b2g/app/B2GLoader.cpp)
|
|-RunProcesses
|
|-fork
|
|-XRE_ProcLoaderServiceRun (nuwa process) (ipc/glue/ProcessUtils_linux.cpp)
| |
| |-mozilla::ipc::ProcLoaderServiceRun
| |
| |-XRE_InitCommandLine
| |
| |-process = new ContentProcess(aPeerPid);
| |
| |-ProcLoaderChild *loaderChild = new ProcLoaderChild(aPeerPid);
| |
| |-loaderChild->Open(transport, aPeerPid, iothread->message_loop());
| |
| |-loop.Run(); // wait until received "load" command
| |
| |-XRE_DeinitCommandLine
| |
| |-sProcLoaderDispatchedTask->DoWork();
| |
| |-content_process_main(argc, argv); // start nuwa. (ipc/contentproc/plugin-container.cpp)
| |
| |-isNuwa |= strcmp(argv[i], "-nuwa") == 0;
| |
| |-XRE_SetProcessType
| |
| |-PrepareNuwaProcess
| |
| |-NuwaAddFinalConstructor(&InitializeBinder, nullptr);
| |
| |-XRE_InitChildProcess (toolkit/xre/nsEmbedFunctions.cpp)
| |
| |-XRE_InitCommandLine
| |
| |-uiLoopType = MessageLoop::TYPE_MOZILLA_CHILD;
| |
| |-MessageLoop uiMessageLoop(uiLoopType);
| |
| |-process = new ContentProcess(parentPID);
| |
| |-process->Init();
| |
| |-uiMessageLoop.MessageLoop::Run(); // run forever
| |
| |-XRE_DeinitCommandLine
|
|
|-XRE_ProcLoaderClientInit (b2g process)
|
|-b2g_main
|
|-XRE_main
|
|-XREMain::XRE_main
|
|-XREMain::XRE_mainRun()
|
|-mozilla::ipc::ProcLoaderClientGeckoInit();
那么,nuwa进程是如何创建一个新的进程的?
b2进程启动时,会在初始化各种共享库后fork一个子进程(nuwa进程),nuwa进程在开始运行后会创建一个ProcLoaderChild对象,并进入message loop进行等待。nuwa进程与b2g进程会进行ipc通讯,当接收到b2g进程发送来的”load”(RecvLoad)命令时,
virtual bool RecvLoad(InfallibleTArray<nsCString>&& aArgv,
InfallibleTArray<nsCString>&& aEnv,
InfallibleTArray<FDRemap>&& aFdsremap,
const uint32_t& aPrivs,
const int32_t& aCookie);
nuwa进程会跳出等待状态,并调用
content_process_main(argc, argv);
对nuwa进程进行初始化工作,最后又进入message loop循环处理各种任务。当接收到b2g进程发送的”fork”(“RecvFork”)命令,
NuwaChild::RecvFork()
- 1
nuwa进程就会创建新的空壳进程。
nsCOMPtr<nsIRunnable> runnable = NS_NewRunnableFunction(&NuwaFork);
MOZ_ASSERT(runnable);
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(NS_DispatchToMainThread(runnable)));
NuwaFork();
- 1
通过下面的图来了解b2g进程、nuwa进程间创建空壳进程的过程:
从以上图可以看出,初始化nuwa使用的是”SendLoad/RecvLoad”命令,而创建空壳进程使用的是”SendFork/RecvFork”。
当创建nuwa完成后(即收到nuwa进程ready信息),b2g进程会主动要求nuwa进程去创建一个空壳进程,日后需要启动应用时,可以直接使用该空壳进程,以加快应用启动速度。
那么,如果系统需要启动一个新的程序,但是已经没有了空壳进程(即mSpareProcesses为空),那b2g进程如何要求nuwa进程去创建一个新的空壳进程呢?
下次再讲讲这个问题~
P.S.
关于nuwa的设计思想,可以看看mozilla的bugzilla:
bugzilla
以及wiki:
wiki