1. 进程和线程
这些都是进程。拥有一定的资源(cpu,内存、磁盘等等)
进程详细解释:当我们启动一个程序时,操作系统会为该程序创建一块内存,用来存放代码、运行中的数据和一个执行任务的主线程,这样的一个运行环境就叫进程。
线程:存在于进程内部,并执行其进程程序的部分功能。多线程可以提升进程的预算效率。
1.1 进程和线程的关系
(1)进程与进程之间的内容相互隔离;
每个进程只能访问自己占有的数据,避免线程之间相互读写数据。如果想要互相通信,走IPC机制。因为进程间的隔离,一个进程挂了,不会影响到其他进程。
(2)进程关闭后,操作系统会回收该进程所占用的内存;
当一个进程退出后,操作系统会回收该进程所申请的所有资源;即使其中任意线程因为操作不当导致内存泄漏,当进程退出时,这些内存也会被正确回收。
(3)进程中的各线程共享该进程的所有数据;
(4)进程中的任意一线程执行出错,都会导致整个进程的崩溃。
2. 浏览器单进程
2007年之前,浏览器都是单进程的。浏览器的所有功能模块都运行在同一个进程中。这些模块包括network、plugin、JS 运行环境、render和UI等。
缺点:
(1)稳定性
早期浏览器依赖非常容易出问题的插件,一个插件的意外崩溃都会导致浏览器的崩溃。在渲染进程中复杂的js代码同理。
(2)性能
由于所有的网页都在一个进程中运行,若存在无限循环的JavaScript代码,将会导致整个浏览器卡顿或者失去响应。并且由于渲染引擎可能存在的内存泄露问题,在关闭时不能完全的回收内存,这样导致的问题是使用时间越长,内存占用越高,浏览器会变得越慢。
(3)安全
由于在同一个进程中运行,通过插件可以获取到操作系统的任意资源,当你在页面运行一个插件时也就意味着这个插件能完全操作你的电脑。
3. 浏览器多进程
Chrome 浏览器右上角点击“选项”>“更多工具”>“任务管理器”,可以看到打开一个页面运行的多个进程。
3.1 早期架构
2008年发布的浏览器架构图:
从图中可以看出,Chrome 的页面是运行在render process中,页面里的插件运行在plugin process之中,进程之间是通过 IPC 机制进行通信(如图中虚线部分)
解决问题
(1)稳定性
各进程之间相互隔离,每个页面的渲染进程相互独立,一个页面或者插件崩溃,不会影响浏览器或者其他页面。
(2)性能
关闭一个页面时,整个渲染进程也会被关闭,之后该进程所占用的内存都会被系统回收。解决了内存泄漏的问题。
(3)安全
chrome把插件进程和渲染进程放到了沙箱中,不能直接访问系统的硬盘、内存和系统权限。
3.2 目前架构
浏览器进程:控制应用程序的“浏览器”部分,主要负责界面的显示、用户交互和子进程管理,同时也提供存储等功能。负责应用程序不同部分的其他进程协调。
渲染进程:核心任务是将 HTML、CSS 和 JavaScript 转换为用户可以与之交互的网页,排版引擎 Blink 和 JavaScript 引擎 V8 都是运行在该进程中,默认情况下,Chrome 会为每个 Tab 标签创建一个渲染进程。出于安全考虑,渲染进程都是运行在沙箱模式下。
GPU 进程:其实,Chrome 刚开始发布的时候是没有 GPU 进程的。而 GPU 的使用初衷是为了实现 3D CSS 的效果,只是随后网页、Chrome 的 UI 界面都选择采用 GPU 来绘制,这使得 GPU 成为浏览器普遍的需求。最后,Chrome 在其多进程架构上也引入了 GPU 进程。
网络进程:主要负责页面的网络资源发起和接收。
插件进程:主要是负责插件的运行,因插件易崩溃,所以需要通过插件进程来隔离,以保证插件进程崩溃不会对浏览器和页面造成影响。
Storage Service进程:为local/session storage, service worker, indexed_db提供存储服务。
3.3 多进程的问题:
(1)更高的资源占用。
因为每个进程都会包含公共基础结构的副本(如 JavaScript 运行环境),这就意味着浏览器会消耗更多的内存资源。
(2)更复杂的体系架构。
浏览器各模块之间耦合性高、扩展性差等问题,会导致现在的架构已经很难适应新的需求了。
4. 未来面向服务的架构
Chromium在2016年提出了以SOA(Services Oriented Architecture)为基础的高内聚,低耦合,易扩展的架构。该架构期望将功能组件以服务的形式拆分或聚合。
同时 Chrome 还提供灵活的弹性架构,在强大性能设备上会以多进程的方式运行基础服务,但是如果在资源受限的设备上(如下图),Chrome 会将很多服务整合到一个进程中,从而节省内存占用。
5. 小问题
因为每开一个页签,通常是开一个新的进程。但是当新开的页面和父页面是同一站点(根域名+协议相同)时,新页面会复用父页面的渲染进程。所以,这种情况下,一个页面崩溃了,会导致同一站点的页面同时崩溃,因为他们使用了同一个渲染进程。
为什么要让他们跑在一个进程里面呢?
因为在一个渲染进程里面,他们就会共享JS的执行环境,也就是说A页面可以直接在B页面中执行脚本。因为是同一家的站点,所以是有这个需求的。
学习笔记参考:https://time.geekbang.org/column/intro/216
https://blog.csdn.net/youzhangjing_/article/details/131416655