浏览器的结构
浏览器的主要组件包括:
用户界面 -- 包括地址栏, 前进 / 后退按钮, 书签菜单等. 除了浏览器主窗口显示用户请求的页面外, 其他显示的各个部分都属于用户界面.
用户界面后端 -- 用于绘制基本的窗口小部件, 比如组合框和窗口. 其公开了与 web 应用无关的通用接口, 而在底层使用操作系统的用户界面方法.
浏览器引擎 -- 在用户界面和渲染引擎之间传递指令.
渲染引擎 -- 负责显示请求的内容. 如果请求的内容是 html, 它就解析 HTML 和 CSS 内容, 并将解析后的内容显示在窗口上.
网络 -- 用于网络调用. 比如 http 请求. 其接口与 Web 应用无关, 并为所有 Web 应用提供底层实现.
JavaScript 解释器. 用于解析和执行 JavaScript 代码, 比如 Chrome 的 JavaScript 解释器是 V8.
数据存储. 这是持久层. 浏览器需要在硬盘上保存各种数据, 例如 cookie. 新的 HTML5 规范定义了 "网络数据库", 这是一个完整的且轻便的浏览器内数据库.
值得注意的是, 不同于大多数浏览器, Chrome 浏览器为每个标签页都分配了各自的渲染引擎实例, 每个标签页都是一个独立的进程(即每个标签页都在独立的 "沙箱" 内运行, 在提高安全性的同时, 一个标签页面崩溃也不会导致其他的标签页被关闭)
浏览器进程与线程
进程是 CPU 资源分配的最小单位(是能拥有资源和独立运行的最小单位)
线程是 CPU 调度的最小单位(线程是建立在进程的基础上的一次程序运行单位, 一个进程可以有多个线程)
浏览器是多进程的, 有一个主控进程, 以及每一个 tab 页面都会新开一个进程(某些情况下多个 tab 会合并进程)
浏览器的进程为以下几种:
Browser 进程: 浏览器的主进程(负责协调, 主控), 只有一个
第三方插件进程: 每种类型的插件对应一个进程, 仅当使用该插件的时候才创建
GPU 进程: 最多一个, 用于 3D 绘制
浏览器渲染进程(内核): 默认每个 tab 页面一个进程, 互不影响, 控制页面渲染, 脚本执行, 事件处理等(有时会优化, 如多个空白 tab 会合成一个进程)
每一个 tab 页面可以看作是浏览器内核进程, 然后这个进程是多线程的, 他又几大类子线程:
GUI 线程
注意: GUI 渲染线程与 JS 引擎线程是互斥的, 当 JS 引擎执行时 GUI 线程会被挂起(相当于被冻结),GUI 更新会被保存在一个队列中等到 JS 引擎空闲时立即被执行
JS 引擎线程
JS 引擎一直等待着任务队列中任务的到来, 然后加以处理, 一个 tab 页中无论什么时候都只有一个 JS 线程在运行 JS 程序
事件触发线程
定时器线程
setInterval 与 setTimeout 所在的线程
浏览器定时器计数器并不是由 JS 引擎计数的,(因为 JS 引擎时单线程的, 如果处于阻塞线程状态就会影响计时的准确)
因此通过单线程来计时并触发定时(计时完毕后, 添加到事件队列中, 等待 JS 引擎空闲后执行)
注意, W3C 在 HTML 标准中规定, 规定要求 setTimeout 中低于 4ms 的时间间隔算为 4ms.
网络请求线程
在 XMLHttpRequest 在连接后是通过浏览器新开一个线程请求
将检测到状态变更时, 如果设置有回调函数, 异步线程就产生状态变更事件, 将这个回调再放入事件队列中. 再由 JavaScript 引擎执行.
每次网络请求时都需要开辟单独的线程进行, 譬如如果 URL 解析到 http 协议, 就会新建一个网络线程去处理资源下载. 因此浏览器会根据解析出得协议, 开辟一个网络线程, 前往请求资源
进程之间的通信
五种通讯方式总结:
管道: 速度慢, 容量有限, 只有父子进程能通讯
FIFO: 任何进程间都能通讯, 但速度慢
消息队列: 容量受到系统限制, 且要注意第一次读的时候, 要考虑上一次没有读完的数据的问题
信号量: 不能传递复杂消息, 只能用来同步
共享内存区: 能够很容易控制容量, 速度快, 但要保持同步, 比如一个进程在写的时候, 另一个进程要注意读写的问题, 相当于线程种的线程安全, 当然, 共享内存区同样可以用作线程间通讯, 不过没有这个必要, 线程间本来就已经共享了统一进程内的一块内存.
由于浏览器每一个 tab 页面即为一个进程, 页面间的通信即为进程的通信
Windows.open(url,name,featrues,replace)
url:(可选)为空则打开空白新窗口
name:(可选)子窗口的句柄. 声明新窗口的名称. 若名字已存在则在指定窗口打开. 仅当同源或该脚本打开了这个窗口才可以通过名字进项指定窗口
Features (可选) 声明新窗口要显示的标准浏览器的特征(必须是打开空白窗口).
Replace(可选) 为 true 的话则替换浏览历史中的当前条目(返回回不去), 默认为 false, 创建新条目.
渲染引擎
渲染引擎也称为浏览器内核, 主要时在浏览器窗口中显示所请求的内容, 这是每个浏览器的核心部分.
常见的浏览器渲染引擎有两种: 一是 Firefox 使用的 Gecko, 这是 Mozilla 公司 "自制" 的渲染引擎. 另一个是 Safari 和 Chrome 使用的都是 webkit.
渲染流程:
渲染引擎一开始会从网络层获取请求的文档的内容, 通常以 8k 分块的方式完成, 获取了文档内容之后, 渲染引擎开始正式工作
渲染引擎解析 HTML 文档, 并将文档中的标签转化为 dom 节点树, 同时, 它会解析外部 CSS 文件以及 style 标签中的样式数据. 这些样式信息连同 HTML 中的可见内容一起, 被用于构建另一颗树 -- 渲染树(RenderTree).
渲染树由一些带有视觉属性 (如颜色, 大小等) 的矩形组成, 这些矩形将按照正确的顺序显示在屏幕上.
渲染树构建完毕之后, 将会进入 "布局" 处理阶段, 即为每一个节点分配一个屏幕坐标. 再下一步就是绘制, 即遍历 renderTree, 并使用 UI 后端层绘制每个节点.
注意: 这个过程时逐步完成的, 为了更好的用户体验, 渲染引擎将会尽可能的早的将内容呈现在屏幕上, 并不会等到所有的 HTML 都解析完成之后再去构建和布局 renderTree. 它时解析完一部分内容就显示一部分内容, 同时, 可能还在通过网络下载其余内容.
来源: https://segmentfault.com/a/1190000017019877