第一句子网 - 唯美句子、句子迷、好句子大全
第一句子网 > b2g process 和nuwa process 通信

b2g process 和nuwa process 通信

时间:2023-12-04 15:16:34

相关推荐

b2g process 和nuwa process 通信

它们通信的目的在于:

b2g要发消息给nuwa,让它fork出web app进程。它们发生在nuwa进程已经完全启动,并准备好fork 其他app子进程。猜想,用的是socket pair 建立关系,ipdl(最终用的是共享内存读写)进行线程级别的信息交互。socket pair只是用于建立通道???

nuwa的操作,从b2g开始fork出两个进程之后,兵分两路,nuwa进程完成自己的所有初始化(包括哪些?)且一直在等待b2g的加载新进程的消息。b2g也一路走下去,完成初始化等,并在appstartup 请求nuwa加载新进程。

具体通信:

/*** How does B2G Loader Work?** <<parent process>><<child process>>* ProcLoaderParent -----> ProcLoaderChild* ^ |* | load()| content_process_main()* | V*ProcLoaderClientNuwa/plugin-container* ^* | ProcLoaderLoad()* ...*ContentParent*** B2G loader includes an IPC protocol PProcLoader for communication* between client (parent) and server (child). The b2g process is the* client. It requests the server to load/start the Nuwa process with* the given arguments, env variables, and file descriptors.** ProcLoaderClientInit() is called by B2G loader to initialize the* client side, the b2g process. Then the b2g_main() is called to* start b2g process.** ProcLoaderClientGeckoInit() is called by XRE_main() to create the* parent actor, |ProcLoaderParent|, of PProcLoader for servicing the* request to run Nuwa process later once Gecko has been initialized.*创建parent actor 用于请求nuwa加载进程* ProcLoaderServiceRun() is called by the server process. It starts* an IOThread and event loop to serve the |ProcLoaderChild|* implmentation of PProcLoader protocol as the child actor. Once it* recieves a load() request, it stops the IOThread and event loop,* then starts running the main function of the content process with* the given arguments.** NOTE: The server process serves at most one load() request.*/

#include "mozilla/ipc/PProcLoaderParent.h"

#include "mozilla/ipc/PProcLoaderChild.h"

gecko/ipc/glue/ProcessUtils_linux.cpp

前b2g:

以上数据函数库等完全准备好了。

完毕之后就开始:

main --> return RunProcesses(argc, argv, reservedFds)

开始fork后分出两个进程进行工作。

nuwa process:

main ->RunProcesses->XRE_ProcLoaderServiceRun -> mozilla::ipc::ProcLoaderServiceRun(aPeerPid:180, aFd:14,aArgc:1, aArgv[...0]:/system/b2g/b2g,aReservedFds[...0]:3)

RunProcesses->XRE_ProcLoaderServiceRun->ProcLoaderServiceRun->

(1XRE_InitCommandLine->XRE_GetBinaryPath(aArgv:/system/b2g/b2g)

(2process= new ContentProcess(aPeerPid:179)--->

ChildThread *iothread = process->child_thread();

(3new ProcLoaderChild(aPeerPid:179)->iothread->message_loop()

ProcLoaderChild *loaderChild = new ProcLoaderChild(aPeerPid)

loaderChild->Open(transport, aPeerPid, iothread->message_loop())

ProcessChild::ProcessChild(ProcessId aParentPid)

: ChildProcess(new IOThreadChild())

, mUILoop(MessageLoop::current())

, mParentPid(aParentPid)

{ ... }

(4BackgroundHangMonitor::Prohibit()

(5loop.Run();

(6 BackgroundHangMonitor::Allow();

(7 XRE_DeinitCommandLine();

(8 int ret = task->DoWork()->int ret = content_process_main(argc, argv)

RunProcesses开始,

nuwa 进程被fork 出来,去执行XRE_ProcLoaderServiceRun->ProcLoaderServiceRun call XRE_InitCommandLine--->

Fuc:RunProcesses ### pid >0 is parentSock(Pid of childSock), or 0 is return by childSock:0

Fuc:RunProcesses ### pid=0,|pid='0',it is childprocess|, isChildProcess=1

Fuc:RunProcesses close parentSock,in nuwa(child) process

Fuc:RunProcesses call XRE_ProcLoaderServiceRun--->

Fuc:RunProcesses XRE_ProcLoaderServiceRun(getppid():181, childSock:14, argc:1, argv:/system/b2g/b2g,aReservedFds[...0]:3)

ipc/glue/ProcessUtils_linux.cpp:672, Fuc:XRE_ProcLoaderServiceRun ----------------------------------

ipc/glue/ProcessUtils_linux.cpp:673, Fuc:XRE_ProcLoaderServiceRun .==nuwa process==. XRE_ProcLoaderServiceRun call mozilla::ipc::ProcLoaderServiceRun(aPeerPid:181, aFd:14,aArgc:1, aArgv[...0]:/system/b2g/b2g,aReservedFds[...0]:3)

ipc/glue/ProcessUtils_linux.cpp:577, Fuc:ProcLoaderServiceRun ----------------------------------

ipc/glue/ProcessUtils_linux.cpp:588, Fuc:ProcLoaderServiceRun aArgv[i]:/system/b2g/b2g

ipc/glue/ProcessUtils_linux.cpp:597, Fuc:ProcLoaderServiceRun call XRE_InitCommandLine--->b2g ,nuwa都要来执行这个模块,为了getbinarypath 二进制可执行文件的地址?

cpp:4583, Fuc:XRE_InitCommandLine ----------------------------------

nuwa 进程被fork 出来,去执行XRE_ProcLoaderServiceRun->ProcLoaderServiceRun ->XRE_InitCommandLine--->

XRE_ProcLoaderServiceRun传入b2g的pid,child的sock 号,就直接去初始化XRE_InitCommandLine,

Fuc:XRE_InitCommandLine XRE_GetBinaryPath(aArgv:/system/b2g/b2g)--->//一样,获取地址

rocessUtils_linux.cpp:610, Fuc:ProcLoaderServiceRun new ContentProcess(aPeerPid:181)--->

rocessChild.cpp:46, Fuc:ProcessChild >>>>>>>>>>>>>>>>>>>>>>>>>>>st.func

rocessUtils_linux.cpp:615, Fuc:ProcLoaderServiceRun new ProcLoaderChild(aPeerPid:181)--->//传入b2g的进程pid,是直接复制b2g一模一样的资源吗?

rocessUtils_linux.cpp:619, Fuc:ProcLoaderServiceRun loaderChild->Open(transport, aPeerPid, iothread->message_loop())//加载子进程并打开,io线程执行message_loop,并与b2g进程进行传输消息?

rocessUtils_linux.cpp:621, Fuc:ProcLoaderServiceRun call BackgroundHangMonitor::Prohibit()--->//禁止后台挂起监控

rocessUtils_linux.cpp:625, Fuc:ProcLoaderServiceRun call loop.Run--->//循环运行

/**

* Run service of ProcLoader.//开启进程加载器的服务端,一直在那里运行,传入参数就是b2g进程的pid,以及socket的文件描述符(父进程的?不对是childSock:14,)

*

* \param aPeerPid is the pid of the parent.

* \param aFd is the file descriptor of the socket for IPC.

*

* See the comment near the head of this file.

*/

static int

ProcLoaderServiceRun(pid_t aPeerPid, int aFd,

int aArgc, const char *aArgv[],

FdArray& aReservedFds)

{

...

}

///

//

b2g process:

1.

1.1main ->RunProcesses->XRE_ProcLoaderClientInit->ProcLoaderClientInit//初始化client 端,各数据供后与nuwa通信用

XRE_ProcLoaderClientInit call mozilla::ipc::ProcLoaderClientInit(aPeerPid:556, aChannelFd:13)

ProcLoaderClientInit sProcLoaderPid:556,sProcLoaderChannelFd:13,sProcLoaderClientInitialized:true

初始化这些数据,供后面nuwa 与b2g 通信时建立连接等。

1.2main ->RunProcesses->b2g_main -> startThreadPool--->//共享线程池

1.3main ->RunProcesses->b2g_main ->XPCOMGlueLoadXULFunctions //再次加载GlueLoadXUL函数

抓重点!!!别看些细枝末节的东西。

1.4b2g_main->do_main -> StartBootAnimation--->//开机动画

1.5main ->RunProcesses->b2g_main -> do_main--->XRE_main

b2g_main->do_main -> XRE_main--->XRE_main::XRE_main()->:

b2g_main->do_main-> XRE_main--->XRE_main::XRE_main()-> XRE_mainInit--->mDirProvider.Initialize-->//初始化目录服务

XRE_mainInit -> XRE_InitCommandLine()-->//xre 主初始化命令行,

XRE_main::XRE_main()-> XRE_mainStartup--->//主启动,版本创建

ScopedXPCOMStartup::Initialize()

XRE_main::XRE_main()->rv = mScopedXPCOM->Initialize()--->NS_InitXPCOM2-->//初始化并启动xpcom等

fork分开之初:

main() ->RunProcesses fork 出2进程后:

main() ->RunProcesses->b2g_main -> XPCOMGlueLoadXULFunctions 不厌其烦地废话!!!

XPCOMGlueLoadXULFunctions 就加载些函数,并不是重点,过。

中间分析:b2g -> nuwa 猜想假设等

RunProcesses XRE_ProcLoaderClientInit(childPid:530, parentSock:13, aReservedFds[...0]:3)

ProcLoaderClientGeckoInit sProcLoaderParent = new ProcLoaderParent()

RunProcesses XRE_ProcLoaderServiceRun(getppid():181, childSock:14, argc:1, argv:/system/b2g/b2g,aReservedFds[...0]:3)

ProcLoaderServiceRun new ContentProcess(aPeerPid:181)--->,

new ProcLoaderChild(aPeerPid:181)

在b2g 和nuwa之间,起触发因素的似乎是appstartup,猜想,是appstartup 提交了启动应用的请求,b2g发消息给nuwa,nuwa结束目前循环,加载出来一个进程(对应一个上层应用),然后把它丢到后台,继续回来接活,直到又有新应用向b2g发请求,说”给我拉起一个进程,让这家伙跑“,nuwa接到活后快乐的去把它拉起来,丢到后台,然后继续出来接活,反反复复。

nuwa其实就是一个进程生产器,生产出来就丢出去,至于它们跟b2g的通信,或者进程和进程之间的通信,应该是它们自己解决,如何呢?ipdl如何运作?以及猜想是否正确,待验证。

b2g总模块:

gecko/toolkit/xre/nsAppRunner.cpp:4569, Fuc:XRE_main >>>>>>>>>>>>>>>>>>>>>>>>>>>st.func

重点分析XRE_main:

结构:

前3个稍微了解即可,初始化启动些必要的东西。简言之,准备数据,数据丢进运行功能模块运行。

NS_InitXPCOM2重点分析:b2g process

b2g process NS_InitXPCOM2部分Log分析:

启动app(nuwa)进程 部分:

较完整版XRE_mainRun

nuwa部分分析:

完整的nuwa process 端Log分析:

b2g 叫相关模块Load nuwa 以及之后,混杂b2g 和nuwa 进程

两进程交互部分:

RunProcesses -> XRE_ProcLoaderClientInit--->//初始化client端,传入nuwa进程的pid,fd,parent sock等

在前面初始化client的时候,ProcLoaderClientInit sProcLoaderPid:530,sProcLoaderChannelFd:13,sProcLoaderClientInitialized:true

这里搞定之后就开始进入b2g_main了,

与上层应用联系的地方?gecko/widget/gonk/nsAppShell.cpp

进程间:

#include "mozilla/ipc/PProcLoaderParent.h"

#include "mozilla/ipc/PProcLoaderChild.h"

gecko/ipc/glue/ProcessUtils_linux.cpp

/*** Initialize the client of B2G loader for loader itself.** The initialization of B2G loader are divided into two stages. First* stage is to collect child info passed from the main program of the* loader. Second stage is to initialize Gecko according to info from the* first stage and make the client of loader service ready.** \param aPeerPid is the pid of the child.* \param aChannelFd is the file descriptor of the socket used for IPC.*/static voidProcLoaderClientInit(pid_t aPeerPid, int aChannelFd){P_LOGI(SEPARATOR_LINE );MOZ_ASSERT(!sProcLoaderClientInitialized, "call ProcLoaderClientInit() more than once");MOZ_ASSERT(aPeerPid != 0 && aChannelFd != -1, "invalid argument");sProcLoaderPid = aPeerPid;sProcLoaderChannelFd = aChannelFd;sProcLoaderClientInitialized = true;P_LOGI("sProcLoaderPid:%d,sProcLoaderChannelFd:%d,sProcLoaderClientInitialized:true",sProcLoaderPid,sProcLoaderChannelFd);}/*** Initialize the client of B2G loader for Gecko.*/voidProcLoaderClientGeckoInit(){P_LOGI(SEPARATOR_LINE );MOZ_ASSERT(sProcLoaderClientInitialized, "call ProcLoaderClientInit() at first");MOZ_ASSERT(!sProcLoaderClientGeckoInitialized,"call ProcLoaderClientGeckoInit() more than once");if (!Preferences::GetBool("dom.ipc.processPrelaunch.enabled", false)) {P_LOGI(" call kill(sProcLoaderPid, SIGKILL)");kill(sProcLoaderPid, SIGKILL);sProcLoaderPid = 0;close(sProcLoaderChannelFd);sProcLoaderChannelFd = -1;return;}sProcLoaderClientGeckoInitialized = true;TransportDescriptor fd;fd.mFd = base::FileDescriptor(sProcLoaderChannelFd, /*auto_close=*/ false);sProcLoaderChannelFd = -1;Transport *transport = OpenDescriptor(fd, Transport::MODE_CLIENT);P_LOGI(" sProcLoaderParent = new ProcLoaderParent()");sProcLoaderParent = new ProcLoaderParent();P_LOGI("sProcLoaderParent->Open(transport,sProcLoaderPid,XRE_GetIOMessageLoop(),ParentSide) ");sProcLoaderParent->Open(transport,sProcLoaderPid,XRE_GetIOMessageLoop(),ParentSide);P_LOGI("call sProcLoaderLoop = MessageLoop::current()--->");sProcLoaderLoop = MessageLoop::current();}/*** Request the loader service, the server, to load Nuwa.*/boolProcLoaderLoad(const char *aArgv[],const char *aEnvp[],const file_handle_mapping_vector &aFdsRemap,const ChildPrivileges aPrivs,ProcessHandle *aProcessHandle){P_LOGI(SEPARATOR_LINE );static int cookie=0;int i;if (sProcLoaderParent == nullptr || sProcLoaderPid == 0) {return false;}AsyncSendLoadData *load = new AsyncSendLoadData();nsTArray<nsCString> &argv = load->mArgv;for (i = 0; aArgv[i] != nullptr; i++) {argv.AppendElement(nsCString(aArgv[i]));}nsTArray<nsCString> &env = load->mEnv;for (i = 0; aEnvp[i] != nullptr; i++) {env.AppendElement(nsCString(aEnvp[i]));}nsTArray<FDRemap> &fdsremap = load->mFdsremap;for (file_handle_mapping_vector::const_iterator fdmap =aFdsRemap.begin();fdmap != aFdsRemap.end();fdmap++) {fdsremap.AppendElement(FDRemap(FileDescriptor(fdmap->first), fdmap->second));}load->mPrivs = aPrivs;load->mCookie = cookie++;*aProcessHandle = sProcLoaderPid;sProcLoaderPid = 0;sProcLoaderLoop->PostTask(FROM_HERE,NewRunnableFunction(AsyncSendLoad, load));return true;}/*** Run service of ProcLoader.** \param aPeerPid is the pid of the parent.* \param aFd is the file descriptor of the socket for IPC.** See the comment near the head of this file.*/static intProcLoaderServiceRun(pid_t aPeerPid, int aFd,int aArgc, const char *aArgv[],FdArray& aReservedFds){P_LOGI(SEPARATOR_LINE );// Make a copy of aReservedFds. It will be used when we dup() the magic file// descriptors when ProcLoaderChild::RecvLoad() runs.sReservedFds = MakeUnique<FdArray>(mozilla::Move(aReservedFds));ScopedLogging logging;char **_argv;_argv = new char *[aArgc + 1];for (int i = 0; i < aArgc; i++) {_argv[i] = ::strdup(aArgv[i]);P_LOGI("aArgv[i]:%s",_argv[i]);MOZ_ASSERT(_argv[i] != nullptr);}_argv[aArgc] = nullptr;gArgv = _argv;gArgc = aArgc;{P_LOGI("call XRE_InitCommandLine--->");nsresult rv = XRE_InitCommandLine(aArgc, _argv);if (NS_FAILED(rv)) {MOZ_CRASH();}TransportDescriptor fd;fd.mFd = base::FileDescriptor(aFd, /*auto_close =*/false);MOZ_ASSERT(!sProcLoaderServing);MessageLoop loop;nsAutoPtr<ContentProcess> process;P_LOGI("new ContentProcess(aPeerPid:%d)--->",aPeerPid);process = new ContentProcess(aPeerPid);ChildThread *iothread = process->child_thread();Transport *transport = OpenDescriptor(fd, Transport::MODE_CLIENT);P_LOGI("new ProcLoaderChild(aPeerPid:%d)--->",aPeerPid);ProcLoaderChild *loaderChild = new ProcLoaderChild(aPeerPid);// Pass a message loop to initialize (connect) the channel// (connection).P_LOGI(" loaderChild->Open(transport, aPeerPid, iothread->message_loop())");loaderChild->Open(transport, aPeerPid, iothread->message_loop());P_LOGI("call BackgroundHangMonitor::Prohibit()--->");BackgroundHangMonitor::Prohibit();sProcLoaderServing = true;P_LOGI("call loop.Run--->");loop.Run();P_LOGI("call BackgroundHangMonitor::Allow()--->");BackgroundHangMonitor::Allow();P_LOGI("call XRE_DeinitCommandLine--->");XRE_DeinitCommandLine();}MOZ_ASSERT(sProcLoaderDispatchedTask != nullptr);ProcLoaderRunnerBase *task = sProcLoaderDispatchedTask;sProcLoaderDispatchedTask = nullptr;P_LOGI("call task->DoWork()--->");int ret = task->DoWork();delete task;for (int i = 0; i < aArgc; i++) {free(_argv[i]);}delete[] _argv;return ret;}#ifdef MOZ_B2G_LOADERvoidXRE_ProcLoaderClientInit(pid_t aPeerPid, int aChannelFd, FdArray& aReservedFds){P_LOGI(SEPARATOR_LINE );// We already performed fork(). It's safe to free the "danger zone" of file// descriptors .mozilla::ipc::CloseFileDescriptors(aReservedFds);P_LOGI(".==b2g process==. XRE_ProcLoaderClientInit call mozilla::ipc::ProcLoaderClientInit(aPeerPid:%d, aChannelFd:%d)",aPeerPid, aChannelFd);mozilla::ipc::ProcLoaderClientInit(aPeerPid, aChannelFd);}intXRE_ProcLoaderServiceRun(pid_t aPeerPid, int aFd,int aArgc, const char *aArgv[],FdArray& aReservedFds){P_LOGI(SEPARATOR_LINE );P_LOGI(".==nuwa process==. XRE_ProcLoaderServiceRun call mozilla::ipc::ProcLoaderServiceRun(aPeerPid:%d, aFd:%d,aArgc:%d, aArgv[...0]:%s,aReservedFds[...0]:%d)",aPeerPid, aFd,aArgc, aArgv[0],aReservedFds[0]);return mozilla::ipc::ProcLoaderServiceRun(aPeerPid, aFd,aArgc, aArgv,aReservedFds);}#endif /* MOZ_B2G_LOADER */

/*** Run service of ProcLoader.** \param aPeerPid is the pid of the parent.* \param aFd is the file descriptor of the socket for IPC.** See the comment near the head of this file.*/static intProcLoaderServiceRun(pid_t aPeerPid, int aFd,int aArgc, const char *aArgv[],FdArray& aReservedFds){P_LOGI(SEPARATOR_LINE );// Make a copy of aReservedFds. It will be used when we dup() the magic file// descriptors when ProcLoaderChild::RecvLoad() runs.sReservedFds = MakeUnique<FdArray>(mozilla::Move(aReservedFds));ScopedLogging logging;char **_argv;_argv = new char *[aArgc + 1];for (int i = 0; i < aArgc; i++) {_argv[i] = ::strdup(aArgv[i]);P_LOGI("aArgv[i]:%s",_argv[i]);MOZ_ASSERT(_argv[i] != nullptr);}_argv[aArgc] = nullptr;gArgv = _argv;gArgc = aArgc;{P_LOGI("call XRE_InitCommandLine--->");nsresult rv = XRE_InitCommandLine(aArgc, _argv);if (NS_FAILED(rv)) {MOZ_CRASH();}TransportDescriptor fd;fd.mFd = base::FileDescriptor(aFd, /*auto_close =*/false);MOZ_ASSERT(!sProcLoaderServing);MessageLoop loop;nsAutoPtr<ContentProcess> process;P_LOGI("new ContentProcess(aPeerPid:%d)--->",aPeerPid);process = new ContentProcess(aPeerPid);ChildThread *iothread = process->child_thread();Transport *transport = OpenDescriptor(fd, Transport::MODE_CLIENT);P_LOGI("new ProcLoaderChild(aPeerPid:%d)--->",aPeerPid);ProcLoaderChild *loaderChild = new ProcLoaderChild(aPeerPid);// Pass a message loop to initialize (connect) the channel// (connection).P_LOGI(" loaderChild->Open(transport, aPeerPid, iothread->message_loop())");loaderChild->Open(transport, aPeerPid, iothread->message_loop());P_LOGI("call BackgroundHangMonitor::Prohibit()--->");BackgroundHangMonitor::Prohibit();sProcLoaderServing = true;P_LOGI("call loop.Run--->");loop.Run();P_LOGI("call BackgroundHangMonitor::Allow()--->");BackgroundHangMonitor::Allow();P_LOGI("call XRE_DeinitCommandLine--->");XRE_DeinitCommandLine();}MOZ_ASSERT(sProcLoaderDispatchedTask != nullptr);ProcLoaderRunnerBase *task = sProcLoaderDispatchedTask;sProcLoaderDispatchedTask = nullptr;P_LOGI("call task->DoWork()--->");int ret = task->DoWork();delete task;for (int i = 0; i < aArgc; i++) {free(_argv[i]);}delete[] _argv;return ret;}

processchild:

gecko/ipc/glue/ProcessChild.cppProcessChild::ProcessChild(ProcessId aParentPid): ChildProcess(new IOThreadChild()), mUILoop(MessageLoop::current()), mParentPid(aParentPid){P_LOGI(STA_LINE);//P_LOGI("ProcessId:%d aParentPid:%d",ProcessId, aParentPid);MOZ_ASSERT(mUILoop, "UILoop should be created by now");MOZ_ASSERT(!gProcessChild, "should only be one ProcessChild");gProcessChild = this;}

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。