CEF3进程模型

CEF3多进程模型

  browser进程:主进程browser进程处理窗口创建、窗口绘制、网络交互以及大部分的主要逻辑。browser进程通常就是宿主进程。
  render进程:blink的渲染和js的执行,通常在分离的render(渲染)进程里。除此之外,render进程还会处理一些逻辑,例如js bindings和dom节点的访问。进程模型默认会为每个唯一源(协议+域)创建一个新的render进程。
  下面尝试了变换新的域名发现(换协议没试),一个browser加载一个新域名的url,会将原有render进程杀掉,创建新的render进程。首先在demo中加载了CSDN首页,发现应用程序中有三个进程PID 85320为browser通常就是宿主进程,PID 85588为gpu加速进程,PID 76600为render进程,如下图:

  然后加载百度的首页,发现browser进程与gpu进程没有发生改变,CSDN的render进程被杀死,cef新创建一个baidu的render进程,PID为87952,如下图:

  若源(协议+域)不变则render进程不会改变。
  其他进程:例如一些插件像flash进程以及处理合成加速的gpu进程等都是按需创建。
  cef3可以通过IPC进行进程间通信,browser和render进程可以通过发送异步消息进行双向通信。

执行体

  主应用执行体通常会多次启动独立的子进程。这是通过传递不同的命令行参数给CefExecuteProcess 函数实现的。如果主应用执行体比较复杂,加载时间花费比较长,宿主程序可以使用分离的执行体去运行这些进程。这种方式是通过初始化cef时设置CefSettings.browser_subprocess_path参数实现的。
  在可执行程序入口点调用CefExecuteProcess函数,开始执行子进程。该函数也可在分离执行体中调用。若在browser进程调用会立即返回-1,在分离执行体中调用会阻塞并在进程退出时返回退出码。下面在windowsQt环境下说明这两种方式的区别:
单一执行体

void print(const QString &cmd)
{
    QFile file("E://aaa.txt");
    QString data = QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss:zzz ") + cmd + "\n";
    file.open(QIODevice::Append);
    file.write(data.toUtf8());
    file.close();
}

int main(int argc, char *argv[])
{
    Application a(argc, argv);

    //命令行参数结构体
    //这个结构体的定义与平台相关
    CefMainArgs main_args(GetModuleHandle(NULL));

    //CefApp接口
    CefRefPtr<BrowserApp> app(new BrowserApp);

    //打印进程命令行
    CefRefPtr<CefCommandLine> commandLine = CefCommandLine::CreateCommandLine();
    commandLine->InitFromString(::GetCommandLineW());
    QString cmd = QString::fromStdString(commandLine->GetCommandLineString().ToString());
    print(cmd);

    //单一执行体,执行子进程
    int exit_code = CefExecuteProcess(main_args, app, NULL);
    if (exit_code >= 0) {
        return -1;
    }

    //设置该结构体,cef初始化时定制行为
    CefSettings settings;

    //开启事件循环
   settings.multi_threaded_message_loop = true;

    //分离执行体
    //QString render = "CEFRender.exe";
    //CefString(&settings.browser_subprocess_path).FromString(render.toStdString());

    //在主进程初始化cef
    CefInitialize(main_args, settings, app, NULL);

    return a.exec();
}

在CefExecuteProcess函数前打印了命令行结果如下:

   由打印结果可知,单一执行体所有开启的进程都会从该执行体的入口点函数(本例为main函数)开始执行。Browser进程执行CefExecuteProcess会立即返回-1,其他进程会阻塞在该函数直到进程退出。也就是说CefExecuteProcess之前的全部代码都会执行。因此,若执行体比较复杂,启动子进程的速度会很慢,也会执行子进程不必要的代码。所以,一般建议使用分离执行体的方式执行子进程。
分离执行体
   分离执行体就是将上面28,29,30,31行注释掉,然后将40,41行的注释打开。CefSettings中的browser_subprocess_path即是指定分离执行体的路径。CEFRender是新建的另一个工程,代码如下:

int WINAPI wWinMain(HINSTANCE hInstance,
    HINSTANCE hPrevInstance,
    LPTSTR lpCmdLine,
    int nCmdShow)
{
    //支持DPI,否则页面显示有问题
    CefEnableHighDPISupport();

    CefMainArgs main_args(hInstance);

    CefRefPtr<BrowserApp> app(new BrowserApp);

    return CefExecuteProcess(main_args, app, NULL);
}

同样在分离执行体进行了打印,执行主应用程序,结果如下:

在任务管理器中可见,主进程browser进程属于CEFDemo执行体,gpu和render进程属于CEFRender执行体。

由此可见,在分离执行体执行子进程,可删除不必要的代码,为子进程定制化程序,提高进程的启动速度,减少开销。

  • 1
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值