乐趣区

关于浏览器:深入理解浏览器中的进程与线程

过程和线程的分割和区别

当咱们启动某个程序时,操作系统会给该程序创立一块内存 (当程序敞开时,该内存空间就会被回收),用来寄存代码、运行中的数据和一个执行工作的主线程,这样的一个运行环境就叫 过程

线程 是依附于过程的,在过程中应用多线程并行处理能晋升运算效率,过程将工作分成很多细小的工作,再创立多个线程,在外面并行别离执行

过程和线程的关系特点是这样的:

  • 过程与过程之间齐全隔离,互不烦扰,一个过程解体不会影响其余过程,防止一个过程出错影响整个程序
  • 过程与过程之间须要传递某些数据的话,就须要通过 过程通信管道 IPC来传递
  • 一个过程中能够并发多个线程,每个线程并行执行不同的工作
  • 一个过程中的任意一个线程执行出错,会导致这个过程解体
  • 同一过程下的线程之间能够间接通信和共享数据
  • 当一个过程敞开之后,操作系统会回收该过程的内存空间

晚期浏览器

2007 年以前浏览器并不是多过程的构造,而是单过程的构造,一个过程中蕴含了网络、JS 运行环境、渲染引擎、页面、插件等,这也导致单过程的构造引发了很多问题

  • 一是 不稳固,其中一个线程卡死,可能会导致整个程序出问题,比方关上多个标签页,其中一个标签页卡死可能会导致整个浏览器无奈失常运行
  • 二是 不平安,浏览器一个过程里是能够共享数据的,那 JS 线程岂不是能够随便拜访浏览器过程内的所有数据,这显然不合理
  • 三是 不晦涩,一个过程须要负责太多事件,会导致运行效率问题

所以为了解决这些问题,才倒退出了多过程构造

咱们来看一下目前最新的 Chrom 有过程架构

Chrome 关上一个页面有多少过程?别离是哪些

浏览器从敞开到启动,而后新开一个页面至多须要: 1 个浏览器过程,1 个 GPU 过程,1 个网络过程,和 1 个渲染过程,一共 4 个过程

后续如果再关上新的标签页:浏览器过程,GPU 过程,网络过程是共享的,不会重新启动,而后默认状况下会为每一个标签页配置一个渲染过程,然而也有 例外,比方从 A 页面外面关上一个新的页面 B 页面,而 A 页面和 B 页面又属于同一站点的话,A 和 B 就共用一个渲染过程,其余状况就为 B 创立一个新的渲染过程

所以,最新的 Chrome 浏览器包含: 1 个浏览器主过程 1 个 GPU 过程 1 个网络过程 多个渲染过程 ,和 多个插件过程

  • 浏览器过程:负责管制浏览器除标签页外的界面,包含地址栏、书签、后退后退按钮等,以及负责与其余过程的协调工作,同时提供存储性能
  • GPU 过程:负责整个浏览器界面的渲染。Chrome 刚开始公布的时候是没有 GPU 过程的,而应用 GPU 的初衷是为了实现 3D CSS 成果,只是前面网页、Chrome 的 UI 界面都用 GPU 来绘制,这使 GPU 成为浏览器广泛的需要,最初 Chrome 在多过程架构上也引入了 GPU 过程
  • 网络过程:负责发动和承受网络申请,以前是作为模块运行在浏览器过程一时在面的,前面才独立进去,成为一个独自的过程
  • 插件过程:次要是负责插件的运行,因为插件可能解体,所以须要通过插件过程来隔离,以保障插件解体也不会对浏览器和页面造成影响
  • 渲染过程:负责管制显示 tab 标签页内的所有内容,外围工作是将 HTML、CSS、JS 转为用户能够与之交互的网页,排版引擎 Blink 和 JS 引擎 V8 都是运行在该过程中,默认状况下 Chrome 会为每个 Tab 标签页创立一个渲染过程

咱们平时看到的浏览器呈现出页面过程中,大部分工作都是在渲染过程中实现,所以咱们来看一下渲染过程中的线程

渲染过程中的线程

  • GUI 渲染线程:负责渲染页面,解析 html 和 CSS、构建 DOM 树、CSSOM 树、渲染树、和绘制页面,重绘重排也是在该线程执行
  • JS 引擎线程 :一个 tab 页中只有一个 JS 引擎线程(单线程),负责解析和执行 JS。 它 GUI 渲染过程不能同时执行,只能一个一个来,如果 JS 执行过长就会导致阻塞掉帧
  • 计时器线程:指 setInterval 和 setTimeout,因为 JS 引擎是单线程的,所以如果处于阻塞状态,那么计时器就会不准了,所以须要独自的线程来负责计时器工作
  • 异步 http 申请线程:XMLHttpRequest 连贯后浏览器开的一个线程,比方申请有回调函数,异步线程就会将回调函数退出事件队列,期待 JS 引擎闲暇执行
  • 事件触发线程:次要用来管制事件循环,比方 JS 执行遇到计时器,AJAX 异步申请等,就会将对应工作增加到事件触发线程中,在对应事件合乎触发条件触发时,就把事件增加到待处理队列的队尾,等 JS 引擎解决

说下浏览器的过程、线程模型,线程模型中的每个线程都是干嘛用的?

Chrome 为例,有四种 过程模型,别离是

  • Process-per-site-instance:默认模式。拜访不同站点创立新的过程,在旧页面中关上的新页面,且新页面与旧页面属于同一站点的话会共用一个过程不会创立
  • Process-per-site:同一站点应用同一过程
  • Process-per-tab:每一个标签页都创立新的过程
  • Single Process:单过程模式

线程模型中的线程都是干嘛的呢?

  • MessagePumpForIO:解决过程间通信的线程,在 Chrome 中,这类线程都叫做 IO 线程
  • MessagePumpForUI:解决 UI 的线程用的
  • MessagePumpDefault:个别的线程用到的

每一个 Chrome 的线程,入口函数都差不多,都是启动一个音讯循环,期待并执行工作

你晓得哪些过程间通信的形式?

  • 管道通信:就是操作系统在内核中开拓一段缓冲区,过程 1 能够将须要交互的数据拷贝到这个缓冲区里,过程 2 就能够读取了
  • 音讯队列通信:音讯队列就是用户能够增加和读取音讯的列表,音讯队列里提供了一种从一个过程向另一个过程发送数据块的办法,不过和管道通信一样每个数据块有最大长度限度
  • 共享内存通信 :就是映射一段能被其余过程拜访的内存,由一个过程创立,但多个过程都能够拜访,共享过程最快的是IPC 形式
  • 信号量通信:比方信号量初始值是 1,过程 1 来拜访一块内存的时候,就把信号量设为 0,而后过程 2 也来拜访的时候看到信号量为 0,就晓得有其余过程在拜访了,就不拜访了
  • socket:其余的都是同一台主机之间的过程通信,而在不同主机的过程通信就要用到 socket 的通信形式了,比方发动 http 申请,服务器返回数据

多标签之间怎么通信?

没有方法间接通信,须要有一个相似中介者进行音讯的转发和接管,比方

  • localStorage:在一个标签页监听 localStorage 的变动,而后当另一个标签页批改的时候,能够通过监听获取新数据
  • WebSocket:因为 websocket 能够实现实时服务器推送,所以服务器就能够来当这个中介者。标签页通过向服务器发送数据,而后服务器再向其余标签推送转发
  • ShareWorker:会在页面的生命周期内创立一个惟一的线程,并开启多个页面也只会应用同一个线程,标签页共享一个线程
  • postMessage

      // 发送方
      window.parent().pastMessage('发送的数据','http:// 接管的址')
      // 接管方
      window.addEventListener('message',(e)=>{let data = e.data})

你晓得僵尸过程和孤儿过程吗?

  • 孤儿过程:故名思义,就是没爹的孩子。父过程退出了,而它的一个或多个过程还在运行,那么这些子过程都会成为孤儿过程。这些孤儿都将被 init 过程收养,并负责这些孤儿的当前
  • 僵尸过程:就是子过程比父过程先完结,而父过程又没有开释子过程占用的资源,那么子过程的形容还留在零碎中,这种过程就是僵尸过程

结语

点赞反对、手留余香、与有荣焉

参考

浏览器工作原理与实际

退出移动版