b2g启动时,运行”/system/b2g/b2g”,入口在”gecko/b2g/app/B2GLoader.cpp”中,如下:
int
main(int argc, const char* argv[])
{
/**
* Reserve file descriptors before loading static data.
*/
FdArray reservedFds;
ReserveFileDescriptors(reservedFds);
/*
* Before fork(), libxul and static data of Gecko are loaded for
* sharing.
*/
bool ok = LoadStaticData(argc, argv);
if (!ok) {
return 255;
}
return RunProcesses(argc, argv, reservedFds);
代码执行流程如下所示:
main() (b2g/app/B2GLoader.cpp)
|
|-ReserveFileDescriptors
|
|-LoadStaticData
|
|-RunProcesses
|
|-fork
|
|-XRE_ProcLoaderServiceRun (child(nuwa) process)
|
|-b2g_main (parent(b2g) process) (b2g/app/nsBrowserApp.cpp)
|
|-android::ProcessState::self()->startThreadPool();
|
|-(void)setsid();
|
|-do_main
|
|-mozilla::StartBootAnimation();
|
|-XRE_main
|
|-XREMain::XRE_main
|
|-new ScopedAppData(aAppData);
|
|-XREMain::XRE_mainInit
|
|-XREMain::XRE_mainStartup
|
|-mScopedXPCOM = MakeUnique<ScopedXPCOMStartup>();
|
|-mScopedXPCOM->Initialize(); (toolkit/xre/nsAppRunner.cpp)
| |
| |-NS_InitXPCOM2 (xpcom/build/XPCOMInit.cpp)
| |
| |-sMessageLoop = new MessageLoopForUI(MessageLoop::TYPE_MOZILLA_UI);
| |
| |-ioThread = MakeUnique<BrowserProcessSubThread>(BrowserProcessSubThread::IO);
| |-ioThread->StartWithOptions
| |
| |-nsThreadManager::get()->Init();
| |
| |-nsTimerImpl::Startup();
| |
| |-nsComponentManagerImpl::gComponentManager = new nsComponentManagerImpl();
| |
| |-nsCycleCollector_init
| |
| |-nsCycleCollector_startup
| |
| |-JS_Init
| |
| |-nsComponentManagerImpl::gComponentManager->Init();(xpcom/components/nsComponentManager.cpp)
| | |
| | |-nsComponentManagerImpl::InitializeStaticModules()
| | |
| | |-RegisterModule(...)
| | |
| | |-greOmnijar =
mozilla::Omnijar::GetReader(mozilla::Omnijar::GRE);
| | |
| | |-cl->location.Init(greOmnijar, "chrome.manifest");
| | |
| | |-nsComponentManagerImpl::RereadChromeManifests
| | |
| | |-nsComponentManagerImpl::RegisterManifest
| | |
| | |-DoRegisterManifest
| | |
| | |-ParseManifest
| | |
| | |-...
| | |
| | |-nsComponentManagerImpl::ManifestContract
| |
| |-XPTInterfaceInfoManager::GetSingleton();
| |
| |-nsDirectoryService::gService->RegisterCategoryProviders();
| |
| |-SharedThreadPool::InitStatics();
| |
| |-AbstractThread::InitStatics();
| |
| |-mozilla::scache::StartupCache::GetSingleton();
| |
| |-mozilla::AvailableMemoryTracker::Activate();
| |
| |-NS_CreateServicesFromCategory(...)
| |
| |-mozilla::HangMonitor::Startup();
| |
| |-mozilla::BackgroundHangMonitor::Startup();
| |
| |-sMainHangMonitor = new mozilla::BackgroundHangMonitor
|
|-XREMain::XRE_mainRun()
|
|-mozilla::ipc::ProcLoaderClientGeckoInit();
|
|-mScopedXPCOM->SetWindowCreator(mNativeApp);
|
|-startupNotifier->Observe(nullptr, APPSTARTUP_TOPIC, nullptr);
|
|-mDirProvider.DoStartup();
|
|-cmdLine->Init(...)
|
|-obsService->NotifyObservers(cmdLine, "command-line-startup", nullptr);
|
|-appStartup->CreateHiddenWindow();
|
|-obsService->NotifyObservers(nullptr, "final-ui-startup", nullptr);
|
|-cmdLine->Run(); (toolkit/components/commandlines/nsCommandLine.cpp)
| |
| |- nsCommandLine::EnumerateValidators
| |
| |-nsCommandLine::EnumerateHandlers
| |
| |-EnumRun
| |
| |-nsICommandLineHandler->Handle (first page will be loaded in here)
|
|-mNativeApp->Enable();
|
|-appStartup->Run(); (toolkit/components/startup/nsAppStartup.cpp)
|
|-mAppShell->Run(); (widget/gonk/nsAppShell.cpp->widget/nsBaseAppShell.cpp)
|
|-MessageLoop::current()->Run(); // run forever~~~~~
b2g进程启动中,会做以下几件事:
1. 在加载库文件之前保留5个文件描述符(从STDERR_FILENO+1开始)
FdArray reservedFds;
ReserveFileDescriptors(reservedFds);
2.加载进程间能共享的各种数据(主要加载libxul等各种共享库,从Omnijar文件中加载各种模块的xpt信息),这样可以节约些内存。
bool ok = LoadStaticData(argc, argv);
3.开始fork进程。父亲就是b2g进程,儿子就是nuwa进程(后续再讲)。其中b2g进程具有系统root权限,负责处理系统的io,显示,操作底层硬件等。
在b2g进程中运行后,需要初始化xpcom,即调用:
rv = NS_InitXPCOM2(&mServiceManager,gDirServiceProvider->GetAppDir(), gDirServiceProvider);
最后,b2g进程会进入一个message loop中,等待处理各种请求:
appStartup->Run();
Firefox OS中进程可以分为三类:b2g进程,nuwa进程,以及content进程。其中content进程都是由nuwa进程生成的(当然在nuwa进程未ready,但又需要fork进程的时候,有可能会由b2g进程直接生成)。
nuwa进程是如何创建新进程?b2g是如何加载第一个程序(system)的?后续文章中进行讲解。