ffos: what Runprocesses does

本文详细解析了B2GLoader的工作流程,包括其IPC协议PProcLoader如何在父进程和子进程间通信,以及B2GLoader如何加载Nuwa进程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

runprocess()

 

 

 

 

in gecko/ipc/glue/ProcessUtils_linux.cpp tell us how B2G works:

/**
 * How does B2G Loader Work?
 *
 *  <<parent process>>      <<child process>>
 *   ProcLoaderParent -----> ProcLoaderChild
 *         ^                       |
 *         | load()                | content_process_main()
 *         |                       V
 *     ProcLoaderClient      Nuwa/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.
 *
 * 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.
 */

gecko/b2g/app/B2GLoader.cpp

 

main(int argc, const char* argv[]) --->

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

XRE_ProcLoaderClientInit(pid_t aPeerPid, int aChannelFd, FdArray& aReservedFds) --->

mozilla::ipc::ProcLoaderClientInit(aPeerPid, aChannelFd) 对client端(b2g process)进行初始化,,设置几个值。如下:

 

gecko/ipc/glue/ProcessUtils_linux.cpp


static void
CloseFileDescriptors(FdArray& aFds)
{
  for (size_t i = 0; i < aFds.length(); i++) {
    unused << HANDLE_EINTR(close(aFds[i]));
  }
}

/**
 * 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 void
ProcLoaderClientInit(pid_t aPeerPid, int aChannelFd)
{
  MOZ_ASSERT(!sProcLoaderClientInitialized, "call ProcLoaderClientInit() more than once");
  MOZ_ASSERT(aPeerPid != 0 && aChannelFd != -1, "invalid argument");
  sProcLoaderPid = aPeerPid;
  sProcLoaderChannelFd = aChannelFd;
  sProcLoaderClientInitialized = true;
}


/**
 * Initialize the client of B2G loader for Gecko.
 */
void
ProcLoaderClientGeckoInit()
{
  MOZ_ASSERT(sProcLoaderClientInitialized, "call ProcLoaderClientInit() at first");
  MOZ_ASSERT(!sProcLoaderClientGeckoInitialized,
             "call ProcLoaderClientGeckoInit() more than once");

  if (!Preferences::GetBool("dom.ipc.processPrelaunch.enabled", false)) {
    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);
  sProcLoaderParent = new ProcLoaderParent();
  sProcLoaderParent->Open(transport,
                          sProcLoaderPid,
                          XRE_GetIOMessageLoop(),
                          ParentSide);
  sProcLoaderLoop = MessageLoop::current();
}

bool ProcLoaderIsInitialized()
{
  return sProcLoaderPid != 0;
}




#ifdef MOZ_B2G_LOADER
void
XRE_ProcLoaderClientInit(pid_t aPeerPid, int aChannelFd, FdArray& aReservedFds)
{
  // We already performed fork(). It's safe to free the "danger zone" of file
  // descriptors .
  mozilla::ipc::CloseFileDescriptors(aReservedFds);

  mozilla::ipc::ProcLoaderClientInit(aPeerPid, aChannelFd);
}

int
XRE_ProcLoaderServiceRun(pid_t aPeerPid, int aFd,
                         int aArgc, const char *aArgv[],
                         FdArray& aReservedFds)
{
  return mozilla::ipc::ProcLoaderServiceRun(aPeerPid, aFd,
                                            aArgc, aArgv,
                                            aReservedFds);
}
#endif /* MOZ_B2G_LOADER */
 main(int argc, const char* argv[]) --->
RunProcesses(argc, argv, reservedFds) --->
XRE_ProcLoaderClientInit(pid_t aPeerPid, int aChannelFd, FdArray& aReservedFds) --->
mozilla::ipc::ProcLoaderClientInit(aPeerPid, aChannelFd)这条线是初始化b2g loader的第一阶段,
主要目的是从b2gloader的main中获取child的信息(即将参数传下来)。b2gloader的初始化的第二阶段大体是将
获取的这些child的参数去初始化gecko 同时使得loader的client 端就绪。

 

 

main(int argc, const char* argv[]) --->

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

return XRE_ProcLoaderServiceRun(getppid(), childSock, argc, argv, aReservedFds) --->

return mozilla::ipc::ProcLoaderServiceRun(aPeerPid, aFd, aArgc, aArgv,aReservedFds);

 

/**
 * 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 int
ProcLoaderServiceRun(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).
    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;
}

 

b2g_main

XRE_main之前xpcom框架已经初始化结束了?是在loadstaicdata 模块下完成的吗?因为直接do_Getservice()了?

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值