阅读 269

浏览器进程与线程

全程以Chrome浏览器为例。

CPU、进程、线程之间的关系

  • 进程是cpu资源分配的最小单位(是能拥有资源和独立运行的最小单位)
  • 线程是cpu调度的最小单位(线程是建立在进程的基础上的一次程序运行单位,一个进程中可以有多个线程)
  • 不同进程之间也可以通信,不过代价较大
  • 单线程多线程,都是指在一个进程内的单和多

浏览器是多进程的

image.png

  • 浏览器是多进程的
  • 每一个Tab页,就是一个独立的进

浏览器进程

  • 主进程
    • 协调控制其他子进程(创建、销毁)
    • 浏览器界面显示,用户交互,前进、后退、收藏
    • 将渲染进程得到的内存中的Bitmap,绘制到用户界面上
    • 处理不可见操作,网络请求,文件访问等
  • 第三方插件进程
    • 每种类型的插件对应一个进程,仅当使用该插件时才创建
  • GPU进程
    • 用于3D绘制等
  • 渲染进程,就是我们说的浏览器内核
    • 负责页面渲染,脚本执行,事件处理等
    • 每个tab页一个渲染进程

我们来看一下实际情况:

查看管理任务:\color{#33CC99}{查看管理任务:}右上角 -> 更多工具 -> 任务管理器 如图所示,Chrome浏览器有多个进程(目前打开两个页签)

1. 浏览器主进程
2. GPU进程
3. Network Service进程
4. Audio Service进程
5. Tracing Service进程
6. 备用渲染程序进程
7. 渲染进程1
8. 渲染进程2
复制代码
  • 浏览器主进程:负责界面显示、用户交互、子进程管理,同时提供存储等功能
  • 渲染进程:将HTML、CSS、JS转换成网页
  • GPU进程:UI绘制
  • Network Service进程:资源加载

这时候呢,如果你再打开一个tab,就会再增加一个渲染进程(也有例外,下面会说到)
这并不是说浏览器只有上述进程,还可能有其他进程,如插件进程(扩展进程)

进程小知识
1. 进程中任意线程出错,进程崩溃
2. 线程共享进程数据
3. 进程之间相互隔离但可以通信
复制代码
课堂小知识
如上所述,打开tab页,会新增一个渲染进程。但有一个例外,就是从页面A打开了页面B,但A、B属于同一站点时,B会复用A的渲染进程,即A、B共用渲染进程
此时一个页面崩溃,另一页面也会崩溃
复制代码
趟坑小知识
如上所述,A、B会共用进程。但也有例外o(╥﹏╥)o
在浏览器地址栏中直接输入地址打开的页面,即使是同一站点,也不会共用进程
复制代码

渲染进程

  • GUI渲染线程
    • 负责渲染页面,布局和绘制
    • 页面需要重绘和回流时,该线程就会执行
    • 与js引擎线程互斥,防止渲染结果不可预期
  • JS引擎线程
    • 负责处理解析和执行javascript脚本程序
    • 只有一个JS引擎线程(单线程)
    • 与GUI渲染线程互斥,防止渲染结果不可预期
  • 事件触发线程
    • 用来控制事件循环(鼠标点击、setTimeout、ajax等)
    • 当处理一些不能立即执行的代码时,会将对应的任务在其可以触发的时机,添加到事件队列的末端
    • 事件循环机制会在JS引擎线程空闲时,循环访问事件队列的头部,如果有函数,则会将该函数推到执行栈中并立即执行
  • 定时触发器线程
    • setInterval与setTimeout所在的线程
    • 定时任务并不是由JS引擎计时的,是由定时触发线程来计时的
    • 计时完毕后,将回调事件放入到事件队列中
  • 异步http请求线程
    • 浏览器有一个单独的线程用于处理AJAX请求
    • 当请求完成时,若有回调函数,将回调事件放入到事件队列中

异步

这里需要理解下事件触发线程定时触发器线程的作用 我们这里有一个事件

image.png

我们知道,不管是setTimeout/setIntervalXHR/fetch代码,在这些代码执行时, 本身是同步任务,而其中的回调函数才是异步任务。

当代码执行到setTimeout/setInterval时,实际上是JS引擎线程通知定时触发器线程,间隔一个时间后,会触发一个回调事件, 而定时触发器线程在接收到这个消息后,会在等待的时间后,将回调事件放入到由事件触发线程所管理的事件队列中。

当代码执行到XHR/fetch时,实际上是JS引擎线程通知异步http请求线程,发送一个网络请求,并制定请求完成后的回调事件, 而异步http请求线程在接收到这个消息后,会在请求成功后,将回调事件放入到由事件触发线程所管理的事件队列中。

当我们的同步任务执行完,JS引擎线程会询问事件触发线程,在事件队列中是否有待执行的回调函数,如果有就会加入到执行栈中交给JS引擎线程执行

GUI渲染线程

  1. 解析HTML构建DOM树
  2. 解析css生成cssom
  3. 结合DOM和CSSOM生成渲染树
  4. 布局阶段(位置计算)
  5. 分层
  6. 生成图层绘制列表
  7. 栅格化操作
  8. 合成与显示
课堂小知识
在控制台输入document可看到完整DOM树
输入document.styleSheets,可以看到样式结构
复制代码
面试小知识
HTML中出现CSS文件的引用,会阻塞DOM树的构建吗?
不会。因为HTML转为DOM树的过程,发现文件请求会交给网络进程去请求文件,渲染进程会继续解析HTML
复制代码
面试小知识
HTML中出现CSS文件的引用,会阻塞页面的渲染吗?
会。因为页面渲染需要CSS样式
复制代码
面试小知识
HTML中出现CSS文件的引用,会阻塞页面的渲染吗?
会。因为页面渲染需要CSS样式
复制代码

宏任务、微任务

宏任务

可以将每次执行栈执行的代码当做是一个宏任务

  • I/O
  • setTimeout
  • setInterval
  • setImmediate
  • requestAnimationFrame
微任务

宏任务执行完,会在渲染前,将执行期间所产生的所有微任务都执行完

  • process.nextTick
  • MutationObserver
  • Promise.then catch finally
整体流程
  • 执行一个宏任务(栈中没有就从事件队列中获取)
  • 执行过程中如果遇到微任务,就将它添加到微任务的任务队列中
  • 宏任务执行完毕后,立即执行当前微任务队列中的所有微任务(依次执行)
  • 当前宏任务执行完毕,开始检查渲染,然后GUI线程接管渲染
  • 渲染完毕后,JS线程继续接管,开始下一个宏任务(从事件队列中获取)

输入url发生了什么

  1. 浏览器进程检查url,组装协议,构成完整url
  2. 浏览器进程通过进程间通信,把url发给网络进程
  3. 网络进程查看该url是否有本地缓存,如果有就返回给浏览器进程
  4. 如果没有,网络进程向web服务器发起http请求
  • 4.1\color{#FF7F50}{4.1} 进行DNS解析,获取IP地址(首先在本地DNS缓存里查找)
  • 4.2\color{#FF7F50}{4.2} 利用ip地址和端口建立TCP连接
  • 4.3\color{#FF7F50}{4.3} 构建请求头信息并发送
  • 4.4\color{#FF7F50}{4.4} 服务器响应后,网络进程接受响应头和响应数据,并解析其内容
  1. 网络进程响应
  • 5.1\color{#FF7F50}{5.1} 检查这状态码,如果是301、302,则从location中读取地址,重新请求
  • 5.2\color{#FF7F50}{5.2} 200处理:检查Content-Type,如果是字节流类型,则提交给下载管理器,不再进行后续渲染;如果是html则通知浏览器进程准备进行渲染
  1. 准备渲染进程
  2. 传输数据,更新状态
  • 7.1\color{#FF7F50}{7.1} 渲染进程准备好后,浏览器进程向渲染进程发起消息,渲染进程收到消息后和网络进程建立传输数据的管道
  • 7.2\color{#FF7F50}{7.2} 渲染进程接收完数据后,向浏览器进程回复消息
  • 7.3\color{#FF7F50}{7.3} 浏览器进程收到消息后更新浏览器界面状态
  1. 渲染进程渲染页面
文章分类
前端
文章标签