浏览器进程线程以及要点笔记

37 阅读6分钟

前言

本文想要明确浏览器有什么进程及其作用,还有就是以浏览器进程线程为框架,更好地去理解那些涉及到不同进程线程的概念(eventloop,url到展示页面等)。

浏览器上的进程和线程

线程与进程概念

对于四个任务,单线程要执行4次,而多线程则只需要执行1次。因此使用并行处理能大大提升性能。 多线程可以并行处理,但线程是不能单独存在的,它需要进程来管理和启动。所以,线程依赖于进程。 一个进程就是一个程序的运行实例,当一个进程启动后,操作系统将会为程序创造一块内存,用来存放代码,运行中的数据和一个执行任务的主线程。我们把这样的运行环境叫做线程。

Image10.png

线程与进程的关系
  1. 进程中任一线程执行错误,会导致整个进程崩溃。
  2. 线程之间共享进程中的数据。都是一片内存空间嘛
  3. 当一个进程关闭后,操作系统会回收进程所占用的内存。(即使因为操作不当导致内存泄漏,当进程退出时,所占用的内存也会被正确回收)
  4. 进程之间的内容互相隔离。
单进程时代的缺陷

Image11.png

1. 不稳定

因为任一线程的执行错误,都会导致进程崩溃,所以,在包含了网络线程,页面线程,插件和渲染引擎等线程的单进程浏览器中,一个线程的意外崩溃都会导致整个浏览器的崩溃。

2. 不流畅

因为在上图中的页面渲染,页面展示,js环境,插件模块都运行在一个线程中,而一个线程一次只能执行一个模块,所以当有一个模块是无限循环或者耗时较长,后面的模块就失去相应或者是卡顿了。

3. 不安全

插件和页面脚本,插件可以使用C/C++等代码编写,通过插件可以获取到操作系统的任意资源,当你在页面运行一个插件时也就意味着这个插件能完全操作你的电脑。如果是个恶意插件,那么它就可以释放病毒、窃取你的账号密码,引发安全性问题。

目前多进程时代的浏览器

目前新的chrome架构

Image12.png

进程的功能:

  • 浏览器主进程(Browser Process): 主要负责界面显示,用户交互,子进程管理,同时提供储存功能。
  • 渲染进程:核心服务是将html,css,js转化为用户可以与之交互的网页。排版引擎blink和js引擎v8都是运行在该进程下,chrome会为每个tab创建一个渲染进程,出于安全考虑,渲染进程都是运行在沙箱环境下。
  • GPU进程:本来GPU是用来实现css 3d效果,但是后来网页和chrome的ui界面都选择采用GPU来绘制。对于GPU的需求变成了刚需,所以chrome在其的多线程架构下也加入了GPU线程
  • 网络进程: 主要负责页面的网络加载。
  • 插件进程:负责插件的运行,因为插件容易崩溃,所以需要通过插件进程来隔离,以保证插件进程的崩溃不会对浏览器和页面造成影响。

所以,打开了一个页面,就会有4个进程,一个GPU进程,一个浏览器主进程,一个渲染进程,一个网络进程。如果开了插件的话,还有插件进程。

重点是浏览器内核:渲染进程

对于普通的前端操作来说,最重要的就是渲染进程了。

浏览器的渲染进程是多线程的,下面列举渲染进程里面有什么线程:

  1. GUI渲染线程

    • 负责渲染浏览器界面,解析HTML,CSS,构建DOM数和Render树,布局和绘制等。
    • 重绘回流都会在这个线程执行。(详情可以看浏览器渲染)
    • 注意GUI渲染线程和JS引擎线程是互斥的,当JS引擎线程在执行的时候GUI渲染线程会被挂起,GUI更新会被保存在一个队列中等到JS引擎空闲时立即被执行。(js引擎可以操作dom,如果在修改这些元素属性同时渲染界面,就是js和gui线程同时运行,那么渲染线程前后获得的数据就不一致了。)
  2. JS引擎线程

    • JS内核,负责解析js代码,执行JS代码。
    • 因为这里解析并执行js代码,所以什么作用域,执行栈,执行上下文都在这。微任务队列也由js引擎线程维护
  3. 事件触发线程

    • 用来控制事件循环,因为js是单线程的,所以很容易忙不过来,需要浏览器另开线程协助。
    • 当js引擎执行到例如setTImeout(是定时触发线程的),或者来自其他线程的事件,AJAX(异步请求线程)等,会把对应的任务添加到事件线程中。
    • 当对应事件触发了符合条件,该线程会把事件添加到待处理队列队尾,等待JS引擎处理,这里的待处理队列,就是宏任务队列
    • 由于js是单线程,所以这些待处理队列都要排队等待js引擎处理。
  4. 定时触发器线程

    • setTImeout和setInterval所在线程。
    • 单线程处于阻塞状态的话,影响计时的准确性,所以单线程来计时并触发计时,当计时完毕后,添加到事件出发线程中的宏任务队列(待处理队列)中。
    • 低于4ms算为4ms
  5. 异步请求http线程

    • 在XMLHttpRequest再连接后通过浏览器新开的一个线程请求。
    • 检测到状态变更的时候,如果设有回调函数,异步线程就会产生状态变更事件,然后这个回调就会放入到事件触发线程里面的宏任务队列中,等js执行。

通过两个例子来看看进程线程之间配合工作

1. event loop事件循环

对于事件循环,这里就简单讲下它的工作原理:

  1. 执行执行栈中的同步代码(就是普通代码),遇到宏任务(setTImeout,ajax请求返回等),则把这些任务push进宏任务队列,遇到微任务(promise,mutationObserver),push进微任务队列。
  2. 等执行栈中的所有任务执行完,执行栈为空的时候,读取微任务队列直到微任务队列为空
  3. 开始读取宏任务队列,重复第一步。

文字上的步骤能够走通,但是在浏览器各线程中又是怎么工作呢?还有,执行栈啊,宏任务微任务队列又是什么关系呢?

下面来看图:

Image13.png

从上面的图为个人理解,有错欢迎纠正,从图可以看出各个概念的关系。不言而喻。

2.浏览器渲染流程

juejin.cn/post/712916…