【Chromium】【笔记】《Chromium 如何显示 Web 页面》《chromium多进程架构》
文章目录
- 原文
- How Chromium Displays Web Pages
- 概念
- The render process
- RenderWidget和RenderView之间有什么区别?
- 胶水层 glue
- Thread in renderer
- The browser process
- Low-level browser process objects
- High-level browser process objects
- TIPS
- Life of a "set cursor" message
- Life of a "mouse click" message
- Multi-process Architecture
- render进程的管理
- 管理 Views
- 组件和接口
- render 进程
- Browser 进程
- 渲染进程的共享
- 检测 renderer 的Crash 和 行为
- renderer 的沙箱运行
- 不常用内存的归还
- 插件与扩展
原文
- How Chromium Displays Web Pages
- Getting Around the Chromium Source Code Directory Structure
- Multi-process Architecture
- 文档部分没更新,新版本的有些已经不同了
How Chromium Displays Web Pages
概念
webkit:是Safari、Chroumium和其他基于webkit浏览器的渲染引擎;
- Port是webkit的一部分,它集成了平台系统依赖服务如:资源装载和图形。
glue:把webkit的类型转化为Chromium的类型,这是我们的“webkit嵌入层”;它是Chroumium和test_shell(用来测试webkit的工具)两个浏览器的基础;
Renderer / Renderer host:这是Chroumium的“多进程嵌入层”,它代理进程间的通知和命令;
webContents:一个重复利用的组件,它是 content 模块中的一个主类,它容易嵌入,可以让多个进程的页面渲染到一个视图中;从Content module可以了解更多的信息。
Browser:代表浏览器窗口,它包含多个webContents。
Tab Helpers:用来连接webContents的单个对象(通过混入WebContentsUserData),浏览器的webContents持有各种各样的Tab Helper(比如一个favicons,一个infobar等)
The render process
- 渲染器中最重要的类是 RenderView,位于 /content/renderer/render_view_impl.cc。
- 这个对象代表一个网页。它处理所有与导航有关的命令,并从浏览器进程中发出。
- 它派生自RenderWidget,提供绘画和输入事件处理。
- RenderView通过全局(每个渲染过程)的RenderProcess对象与浏览器进程进行通信。
RenderWidget和RenderView之间有什么区别?
- RenderWidget通过 实现胶合层中名为WebWidgetDelegate的抽象接口,映射到一个WebCore::Widget对象。这基本上是屏幕上的一个Window,它接收输入事件,我们在其中作画。
- RenderView继承自RenderWidget,是一个标签或弹出窗口的内容。它除了处理Widget的绘画和输入事件外,还处理导航命令。
- 只有一种情况下,RenderWidget的存在没有RenderView,那就是网页上的选择框。这些是带有向下箭头的框,会弹出一个选项列表。选择框必须用一个本地窗口来渲染,这样它们就可以出现在其他东西上面,必要时还可以跳出框架。这些窗口需要绘制和接收输入,但并没有一个单独的 “网页”(RenderView)给它们
胶水层 glue
- 胶水层 glue
- 将原本不兼容的程序或软件组件结合起来,专门作为两个不兼容的软件片段之间的代理
- WebKit的 "glue "层:也是一个chromium 和 WebKit 的中间层。
- WebKit的 "glue "层将Chromium代码库的其他部分与WebCore的数据类型隔离开来,以帮助减少WebCore变化对Chromium代码库的影响
Thread in renderer
- 每个渲染器都有两个线程
- 渲染线程是主要对象(如 RenderView 和所有 WebKit 代码)运行的地方。
- 当它与浏览器进行通信时,消息首先被发送到主线程,然后由主线程将消息分派给浏览器进程。、
- 这让我们可以从renderer 向browser 同步发送消息。
- 当JavaScript请求时,获取一个页面的cookie。renderer线程会阻塞,而主线程会排队等待所有收到的消息,直到找到正确的响应。在此期间收到的任何消息随后都会被发布到渲染器线程中进行正常处理。
The browser process
Low-level browser process objects
所有与render 进程的IPC通信都在browser 的I/O线程上完成。这个线程也处理所有的网络通信,这使它不会干扰到用户界面。
当RenderProcessHost在主线程(用户界面运行的地方)上被初始化时,它会创建一个新的渲染器进程和一个ChannelProxy IPC对象,该对象有一个指向渲染器的命名管道。
- 这个对象在浏览器的I/O线程上运行,监听指向渲染器的指定管道,并自动将所有消息转发回用户界面线程上的RenderProcessHost。
- 一个ResourceMessageFilter将被安装在这个通道中,它将过滤掉某些可以直接在I/O线程上处理的消息,例如网络请求。这种过滤发生在ResourceMessageFilter::OnMessageReceived。
UI线程上的RenderProcessHost负责将所有特定于视图的消息分派给适当的RenderViewHost(它自己处理有限数量的非视图特定的消息)。这种调度发生在RenderProcessHost::OnMessageReceived。
High-level browser process objects
视图特定的消息会进入RenderViewHost::OnMessageReceived。大部分的消息在这里被处理,其余的被转发到RenderWidgetHost基类。
这两个对象映射到renderer 中的RenderView和RenderWidget 。
- 每个平台都有一个视图类(RenderWidgetHostView[Aura|Gtk|Mac|Win])来 实现与本地视图系统的集成。
在RenderView/Widget 之上是WebContents对象,大多数消息实际上 最终都是对该对象的函数调用。
- WebContents代表了一个网页的内容。它是内容模块的顶层对象,负责在矩形视图中显示网页。content module
WebContents对象包含在一个TabContentsWrapper中。那是在chrome/中,负责一个标签。
TIPS
Life of a “set cursor” message
设置光标是一个典型消息的例子,它从Render发送到Browser,在Render中发生了以下情况:
- 设置光标消息在Webkit的内部产生,一般是相应输入事件,设置光标消息在RenderWidget::SetCursor(应该是didChangeCursor)开始,这个函数在content/renderer/render_widget.cc中;
- RenderWidget::SetCursor调用RenderWidget::Send分发该消息,这个函数也被RenderView用来发送消息给Browser,接下来调用RenderThread::Send;
- 调用IPC::SyncChannel内部代理消息给render的主线程,主线程投递消息给命名管道,从而发送给Browser;
然后Browser采取控制:
- 在RenderProcessHost中的IPC::ChannelProxy接收Browser的I/O线程的所有消息,首先通过ResourceMessageFilter发送,在I/O线程里直接分发网络和相关消息;既然我们的消息没有被过滤掉,它们继续送到Browser的UI线程(IPC::ChannelProxy在内部处理);
- 在content/browser/renderer_host/render_process_host_impl.cc的RenderProcessHost::OnMessageReceived收到对应Render进程的所有视图的消息,它直接处理部分消息,其余的转发给发送消息的原RenderView对应的RenderViewHost;
- 消息到达位于content/browser/renderer_host/render_view_host_impl.cc的RenderViewHost::OnMessageReceived,许多消息在这里处理;但’set cursor’消息不是在这里处理,因为它是从RenderWidget发送,要被RenderWidgetHost处理;
- 所有未在RenderViewHost处理的消息自动转发给RenderWidgetHost,包括我们的设置光标消息(set cursor message);
- 在content/browser/render_host/render_view_host_impl.cc的消息映射最后在RenderWidgetost收到该消息,调用适当的界面(UI)函数来设置鼠标光标
Life of a “mouse click” message
发送鼠标点击是一个典型的从浏览器发送消息到渲染进程(renderer)
- 窗口消息在浏览器的界面线程中的RenderWidgetHostViewWin::OnMouseEvent被接收到,然后调用同类的函数ForwardMouseEventToRender;
- 该转发函数把输入事件封包成跨平台的WebMouseEvent,最后发送给相关的RenderWidgetHost;
- RenderWidgetHost::ForwardInputEvent创建一个进程间通信消息ViewMsg_HandleInputEvent,序列化进WebInputEvent,并呼叫RenderWidgetHost::Send;
- RenderWidgetHost::Send正好转发给RenderProcessHost::Send函数,轮流发送消息给IPC::ChannelProxy;
- 在内部IPC::ChannelProxy代理消息给浏览器的I/O线程并写进对应的渲染(renderer)进程的命名管道
注意许多其他类型的消息都在WebContents中创建,特别是导航系列,都遵循一个从WebContents到RenderViewHost的简单路径;
然后渲染进程采取控制
渲染主线程侧的IPC::Channel读取浏览器发送过来的消息,IPC::ChannelProxy代理给渲染线程;
RendView::OnMessageReceived获取这个消息,许多消息都在这里处理;然而点击消息不在这里处理,它和其他未处理的消息直接到达RenderWidget::OnMessageReceived,再轮流转发给RenderWidget::OnHandleInputEvent;
输入事件转给WebWidgetImpl::HandleInputEvent,在这里转变为一个WebKit platformMouseEvent类,在传入给webkit的内部WebCore::Widget类;
Multi-process Architecture
- chromium 的多进程,保证了单个render 进程的崩溃不会引起整个浏览器的崩溃、限制了render进程的权限(沙箱)
- renderer 使用Blink 作为解释和布局HTML 的引擎。
RenderProcess & RenderView与其Host
render进程的管理
- 每个render进程都有一个全局的
RenderProcess
对象,它负责管理与父浏览器进程的通信,并维护全局状态。 - Browser 为每个render 进程维护一个相应的
RenderProcessHost
,它管理浏览器状态并和 renderer 通信。- Browser和renderer使用 Chromium 的 IPC 系统进行通信。
管理 Views
- 每个render 进程 都有一个或多个 RenderView 对象,由 RenderProcess 管理,它们对应于content 的标签。
- 相应的RenderProcessHost会维护一个RenderViewHost,与renderer 中的每个view 对应。
- 每个view都被赋予一个
viewID
,用来区分同一renderer 中的多个view。 - 这些ID在一个renderer 中是唯一的,但在Browser中不是,所以识别一个视图需要一个RenderProcessHost和一个viewID。
- 每个view都被赋予一个
- 从Browser 到特定标签content 的通信是通过这些RenderViewHost对象完成的,它们知道如何通过它们的RenderProcessHost向RenderProcess发送消息,然后再发送到RenderView。
- 即 RenderViewHost => RenderProcessHost => RenderProcess => RenderView,后两个在 render 进程中。
- 相应的RenderProcessHost会维护一个RenderViewHost,与renderer 中的每个view 对应。
组件和接口
render 进程
RenderProcess
处理与Browser 中相应的RenderProcessHost
的IPC 通信。- 每个 render 进程正好有一个
RenderProcess
对象。这就是所有浏览器↔渲染器的通信方式。
- 每个 render 进程正好有一个
RenderView
对象与Browser 进程中相应的RenderViewHost
(通过RenderProcess
)以及我们的WebKit嵌入层进行通信。RenderView
对象在一个标签或弹出窗口中 代表一个网页的内容。
Browser 进程
- Browser对象代表一个顶级的Browser窗口。
RenderProcessHost
对象代表一个 Browser ↔ Renderer IPC连接的Browser 端。- 在Browser进程中,每个render 进程都 对应着 一个
RenderProcessHost
。
- 在Browser进程中,每个render 进程都 对应着 一个
RenderViewHost
对象封装了与远程RenderView
的通信,而RenderWidgetHost
处理Browser 中RenderWidget
的输入和绘制。
渲染进程的共享
一般来说,每个新的窗口或标签都会在一个新的进程中打开。Browser会生成一个新的进程,并指示它创建一个
RenderView
。有时,在 tabs 或窗口之间共享 Render 进程是必要的或可取的。
- 一个web app 打开了一个新的窗口,希望与之进行同步通信,例如,在JavaScript中使用window.open。在这种情况下,当我们创建一个新的窗口或 tab 时,我们需要重新使用该窗口被打开的 进程。
我们也有一些策略,如果进程的总数太大,或者用户已经打开了一个导航到该领域的进程,我们可以将新标签分配给现有的进程。
详情:Process Models
检测 renderer 的Crash 和 行为
- 与Browser 进程的每个IPC连接都会观察进程句柄。
- 如果这些句柄被发出信号,说明渲染器进程已经崩溃了,标签会被通知崩溃。
- 现在,我们通过显示一个 “sad tab” 页面,以通知用户 renderer 已经崩溃了。
- 该页面可以通过按下重载按钮或开始一个新的导航来重新加载。
renderer 的沙箱运行
鉴于renderer是在一个独立的进程中运行的,我们有机会通过沙盒来限制它对系统资源的访问。
- 例如,我们可以确保renderer只能通过其父级 Browser 进程来访问网络。同样地,我们也可以利用OS 的内置权限来限制它对文件系统的访问。(进程创建或直接标明文件操作权限)
除了限制renderer 对文件系统和网络的访问外,我们还可以限制它对用户的显示器和相关对象的访问。
- 我们在一个单独的Windows "桌面 "上运行每个渲染进程,而用户是不可见的。这可以防止被破坏的renderer 打开新的窗口或捕获按键。
不常用内存的归还
鉴于renderer 是在独立的进程中运行的,因此将隐藏的tab 视为低优先级就变得很直接了。
- 通常情况下,Windows上最小化的进程会将其内存自动放入一个 "available memory "池中。
- 在低内存的情况下,Windows会在换出高优先级的内存之前将这些内存换到磁盘上,以帮助保持用户可见的程序更多的响应。(内存置换)
- 我们可以将这一原则应用于隐藏标签。当一个渲染进程没有顶层标签时,我们可以释放该进程的 "working set " ,作为对系统的提示,在必要时先将该内存换出到磁盘。
- 因为我们发现,当用户在两个标签之间切换时,减少 working set 的大小也会降低标签的切换性能,所以我们逐渐释放这部分内存。
- 这意味着,如果用户切换回最近使用的标签,该标签的内存比最近很少使用的标签更可能 to be paged 。//
- 拥有足够内存来运行所有程序的用户根本不会注意到这个过程。 Windows只有在需要时才会实际回收这些数据,所以在内存充足的情况下,不会有性能上的影响。
- 通常情况下,Windows上最小化的进程会将其内存自动放入一个 "available memory "池中。
这有助于我们在低内存情况下获得更理想的内存占用率。与很少使用的后台标签相关的内存可以完全被交换出去,而前台标签的数据可以完全被加载到内存中。
相比之下,一个单进程的浏览器会将所有标签的数据随机地分布在其内存中,而且不可能将已使用和未使用的数据分离得如此干净,这既浪费了内存也浪费了性能。(多进程的另一个好处)
插件与扩展
- 插件和扩展运行在单独的 进程中。(多个tab 的插件同样运行在一个插件进程中)
【Chromium】【笔记】《Chromium 如何显示 Web 页面》《chromium多进程架构》相关推荐
- pyqt5中显示web页面(外部web、本地web)
本文涉及:Windows操作系统,PyChrm,PyQt5,Qt Designer,pyecharts 目录 一.前言 二.实战示例:在frame控件中显示pyecharts生成的图表 三.实战示例: ...
- Web 页面请求过程
1.DHCP 配置主机信息 假设主机最开始没有 IP 地址以及其它信息,那么就需要先使用 DHCP 来获取. 主机生成一个 DHCP 请求报文,并将这个报文放入具有目的端口 67 和源端口68 的 U ...
- chromium笔记
chromium笔记 源码下载 chromium下载与编译 chromium版本 编译错误 & 解决方法 chrome源码编译常见的错误解决 chromium下载历史版本错误
- PHP学习笔记-PHP与Web页面的交互2
转载请标明出处: http://blog.csdn.net/hai_qing_xu_kong/article/details/51761308 本文出自:[顾林海的博客] 前言 在<PHP学习笔 ...
- Chromium多进程架构简要介绍和学习计划
Chromium以多进程架构著称,它主要包含四类进程,分别是Browser进程.Render进程.GPU进程和Plugin进程.之所以要将Render进程.GPU进程和Plugin进程独立出来,是为了 ...
- PHP学习笔记-PHP与Web页面的交互1
转载请标明出处: http://blog.csdn.net/hai_qing_xu_kong/article/details/51660273 本文出自:[顾林海的博客] 前言 这篇笔记记录的是Web ...
- vs2008与IIS 7.0使用在vista上时出现的问题及解决方法(Internet Explorer 无法显示该页面)(VS2008: IE Cannot Display Web Page)...
我的系统是Vista Ultimate SP1,先安装了vs2008 ,然后再安装了IIS7.0之后就出现了一系列的问题. 问题:通过vs2008启动程序调试时报错.错误提示为:Internet Ex ...
- ASP.NET Web页面(.aspx)添加用户控件(.ascx)无显示的问题
写好的用户控件点击视图显示没有问题,但是将控件添加到Web窗体上时却显示如下图标: F5运行,查看源代码:有代码--但是页面却显示一片空白. 分析代码,比较了一下能显示用户控件的其他web页面以及代码 ...
- 前端app调起摄像头 只显示在页面_猫也能看得懂的教程之一分钟使用Vue搭建简单Web页面...
本教程适合人群: 已经了解过过html.js.css,想深入学习前端技术的小伙伴 有前端开发经验.但是没有使用过Vue的小伙伴 有过其他编程经验,对前端开发感兴趣的小伙伴 学习本教程之后你将会: 了解 ...
最新文章
- linux卸载欧朋浏览器,如何在Centos下安装opera浏览器
- Linux下用Xdebug调试php
- 一个简单的配置管理器(SettingManager)
- Logistic Regression and Classification
- 非科班的java程序员该如何补充计算机基础知识,需要看哪些书?
- python使用json实现树结构_js怎样将获取json转换为树形结构
- Log.isDebugEnabled()使用场景
- grep 显示包含两个关键字_linux三剑客之-grep
- 【dp】P1077 摆花
- “让我陪你走到人生的尽头。” | 也许AI能提供更好的临终关怀
- 巴菲特如何滚雪球的?
- 支持!解决卡巴斯基程序错误及程序断开的问题!
- 【心情】2016ICPC青岛站打铁记
- 运筹说 第92期|爱思唯尔“高被引学者“
- 1、SONIX单片机新建工程与烧录流程
- springboot+vue旅游景点酒店预订系统网站
- 7-基本数据类型和复合数据类型(引用数据类型)
- JS人民币小写金额转换为大写(没毛病)
- typescript学习之路(三) —— ts定义类的方法(包含es5以及es6的定义类)
- 发明专利申请的必要条件