CEF3进程模型

it2022-05-05  173

CEF3多进程模型

  browser进程:主进程browser进程处理窗口创建、窗口绘制、网络交互以及大部分的主要逻辑。browser进程通常就是宿主进程。   render进程:blink的渲染和js的执行,通常在分离的render(渲染)进程里。除此之外,render进程还会处理一些逻辑,例如js bindings和dom节点的访问。进程模型默认会为每个唯一源(协议+域)创建一个新的render进程。   下面尝试了变换新的域名发现(换协议没试),一个browser加载一个新域名的url,会将原有render进程杀掉,创建新的render进程。首先在demo中加载了首页,发现应用程序中有三个进程PID 85320为browser通常就是宿主进程,PID 85588为gpu加速进程,PID 76600为render进程,如下图:   然后加载百度的首页,发现browser进程与gpu进程没有发生改变,的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执行体。 由此可见,在分离执行体执行子进程,可删除不必要的代码,为子进程定制化程序,提高进程的启动速度,减少开销。


最新回复(0)