浏览器的进程和线程

138 阅读6分钟

线程和进程的概念

进程:进程是正在运行的程序的实例。它包含了程序代码、数据、系统资源等,每当电脑开启一个程序,就相当于开启了一个进程。

线程:线程是进程的一部分,是一个执行路径。一个进程可以包含多个线程,它们共享进程的资源和上下文。

特点:

  • 每个进程都有独立的内存空间,不同进程之间无法直接访问对方的内存。
  • 进程之间是相互独立的,一个进程的崩溃不会影响其他进程。
  • 线程之间共享同一进程的地址空间,可以直接访问进程的内存。
  • 多个线程之间共享相同的资源,包括文件句柄、打开的网络连接等。
  • 一个进程中的多个线程之间可以方便地进行通信,因为它们共享相同的上下文。
  • 当一个进程关闭之后,操作系统会回收该进程的内存空间

多进程的浏览器

浏览器从关闭到启动,然后新开一个页面至少需要:1个浏览器进程,1个GPU进程,1个定时器引擎,1个网络进程,和1个渲染进程,1个插件进程

浏览器的主进程(只有一个),负责协调、主控。

各个进程的作用

渲染进程

  • 渲染浏览器界面,解析HTML,CSS,创建DOM,布局绘制都需要该进程
  • 当界面需要重绘(Repaint)或由于某种操作引发回流(reflow)时,该线程就会执行

这里面包括

  • GUI渲染线程
  • JavaScript引擎线程
  • 事件触发线程
  • 定时器线程
  • 异步http请求线程

GPU进程

用于3D绘制,将开启了3D绘制的元素渲染由CPU转向GPU,最多一个。

定时器进程

  • 如其名,就是处理setTimeout,setInterval的线程
  • 浏览器定时计数器并不是由 JavaScript 引擎计数的,(因为 JavaScript 引擎是单线程的, 如果处于阻塞线程状态就会影响记计时的准确)。

网络进程

  • 在 XMLHttpRequest 在连接后是通过浏览器新开一个线程请求。
  • 将检测到状态变更时,如果设置有回调函数,异步线程就产生状态变更事件,将这个回调再放入事件队列中。再由 JavaScript 引擎执行。

插件进程

每种类型的插件对应一个进程,仅当使用该插件时才创建,当一个插件出现了错误,并不会影响主线程。

浏览器里面的线程

图片

JS引擎线程

  • 负责处理JS的脚本的进程
  • 渲染线程与 JS 引擎线程是互斥的,所以如果 JS 执行的时间过长,这样就会造成页面的渲染不连贯,导致页面渲染加载阻塞。

事件触发线程

  • 用来控制事件循环的,该任务不是属于JS引擎进程的而属于事件触发进程,也就是JS引擎忙不过来,再开了一个进程来处理
  • 当遇到一些异步请求耗时的任务,会把他们放到任务队列里面

定时器线程

  • 如其名,就是处理setTimeout,setInterval的线程
  • 浏览器定时计数器并不是由 JavaScript 引擎计数的,(因为 JavaScript 引擎是单线程的, 如果处于阻塞线程状态就会影响记计时的准确)。

网络请求线程

  • 在 XMLHttpRequest 在连接后是通过浏览器新开一个线程请求。
  • 将检测到状态变更时,如果设置有回调函数,异步线程就产生状态变更事件,将这个回调再放入事件队列中。再由 JavaScript 引擎执行。

主线程和内核进程之间的通信

  • Browser 进程收到用户请求,首先需要获取页面内容(譬如通过网络下载资源),随后将该任务通过 RendererHost 接口传递给 Render 进程。
  • Renderer 进程的 Renderer 接口收到消息,简单解释后,交给 GUI 渲染线程,然后开始渲染。
  • 渲染线程接收请求,加载网页并渲染网页,这其中可能需要 Browser 进程获取资源和需要 GPU 进程来帮助渲染。
  • 当然可能会有 JS 线程操作 DOM(这样可能会造成回流并重绘)。
  • 最后 Render 进程将结果传递给 Browser 进程。
  • Browser 进程接收到结果并将结果绘制出来

进程之间的通信方式(了解即可)

  • 管道通信:就是操作系统在内核中开辟一段缓冲区,进程1可以将需要交互的数据拷贝到这个缓冲区里,进程2就可以读取了

  • 消息队列通信:消息队列就是用户可以添加和读取消息的列表,消息队列里提供了一种从一个进程向另一个进程发送数据块的方法,不过和管道通信一样每个数据块有最大长度限制

  • 共享内存通信:就是映射一段能被其他进程访问的内存,由一个进程创建,但多个进程都可以访问,共享进程最快的是IPC方式

  • 信号量通信:比如信号量初始值是1,进程1来访问一块内存的时候,就把信号量设为0,然后进程2也来访问的时候看到信号量为0,就知道有其他进程在访问了,就不访问了

  • socket:其他的都是同一台主机之间的进程通信,而在不同主机的进程通信就要用到socket的通信方式了,比如发起http请求,服务器返回数据

多标签之间的通信

  • localstorage: 同域共享存储空间,持久化将数据存储来浏览器,提供事件监听localStorage变化
  • websocket:它是一个全双工通信的协议,意味着客户端和服务端可以互相通信,享受平等关系。最简单例子就是聊天室,我们在聊天室里面可以收消息,也可以发消息,只要我们与服务端通过websocket建立好了连接。没有同源共享策略,即可实现跨域共享
  • SharedWorker:sharedWorker就是webWorker中的一种,它可以由所有同源页面共享,利用这个特性,我们就可以使用它来进行多标签页之间的通信。如果url相同,且是同一个js,那么只会创建一个sharedWorker,多个页面共享这个sharedWorker
  • webWorker:Web Worker 为代码在后台线程中运行脚本提供了一种简单方法,线程可以执行任务而不干扰用户界面。
// 发送方 
window.parent().postMessage('发送的数据','http://接收的址')
// 接收方 
window.addEventListener('message',(e)=>{ let data = e.data })

总结

  1. 浏览器是多进程的
  2. JS引擎是单线程的,并且会阻塞GUI渲染线程