2.浏览器原理之进程和线程

本文深入探讨了线程和进程的概念、关系及区别,包括僵尸进程、孤儿进程和死锁。详细介绍了Chrome浏览器的多进程架构,如浏览器进程、渲染进程、GPU进程和网络进程,以及各个进程中的线程,如GUI渲染线程、JS引擎线程等。同时,阐述了浏览器内多个标签页间的通信方法,并解析了ServiceWorker在浏览器缓存中的作用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. 线程和进程

1)进程和线程的概念

进程Process是资源分配的最小单位;线程Thread是cpu调度的最小单位

2)进程和线程的关系

  • 进程中的任意一个线程执行错误,都会导致整个进程的崩溃
  • 线程之间共享进程中的数据
  • 当一个进程关闭之后,操作系统会回收进程所占用的内存,当一个进程退出时,操作系统会回收该进程所申请的所有资源;即使其中任意线程因为操作不当导致内存泄露(不再用到的内存,没有及时释放,就算内存泄漏(memory leak),当进程退出时,这些内存也会被正确回收。
  • 进程之间的内容相互隔离。进程隔离就是为了使操作系统中的进程互不干扰,每一个进程只能访问自己占有的数据,也就避免出现进程A写入数据到进程B到情况。正是因为进程之间的数据时严格隔离的,所以一个进程如果崩溃了,或者挂起了,是不会影响到其他进程的。如果进程之间需要进行数据的通信,这时候,就需要使用用于进程间的通信机制了

3)进程和线程的区别

  • 进程可以看做独立应用,线程不能
  • 资源:进程是cpu资源分配的最小单位(是能拥有资源和独立运行的最小单位);线程是cpu调度的最小单位(线程是建立在进程的基础上一次程序运行单位,一个进程可以有多个线程)
  • 通信方面:线程间可以通过直接共享同一进程中的资源,而进程通信需要借助进程间通信。
  • 调度:进程切换比线程切换的开销大。线程是cpu调度的基本单位,线程的切换不会引起进程切换,但某个进程中的线程切换到另一个进程中的线程时,会引起进程切换。
  • 系统开销:由于创建或者撤销进程时,系统都要为之分配或者回收资源,如内存,I/O等,其开销远大于创建或撤销线程时的开销。同理,在进行进程切换时,涉及当前执行进程CPU环境还有各种各样状态的保存及新调度进程状态的设置,而线程切换时只需要保存和设置少量寄存器内容,开销较小。

4)僵尸进程

子进程比父进程先结束,而父进程又没有释放子进程占有的资源,那么子进程的进程描述符仍然保存在系统中,这种进程称为僵尸进程。

5)孤儿进程

父进程退出了,而它的一个或多个子进程还在运行,那这些子进程都会成为孤儿进程。孤儿进程将被init进程(进程号为1)所收养,并由init进程对它们完成状态的收集工作。

6)死锁

所谓死锁,是指多个进程在运行过程中因为争夺资源而造成的一种僵局,当进程处于这种僵持状态时,若无外力作用,它们都将无法再向前推进。

7)进程之间的通信方式

  • 管道通信
  • 消息队列通信
  • 信号量通信
  • 信号通信
  • 共享内存通信
  • 套接字通信

2.Chrome浏览器的架构图

谷歌浏览器
从图中可以看出,最新的浏览器包括:1个浏览器主进程,1个GPU进程,1个网络进程,多个渲染进程,多个插件进程。

  • 浏览器进程:主要负责界面显示,用户交互,子进程管理,同时提供存储等功能。
  • 渲染进程:核心任务是将HTML,CSS和JavaScript转换为用户可以与之交互等网页,排版引擎Blink和JavaScript引擎V8都运行在该进程中,默认情况下,Chrome会为每个Tab标签创建一个渲染进程。处于安全考虑,渲染进程都是运行在沙箱模式下。
  • GPU进程:其实,GPU的使用初衷是为了实现3D CSS效果,只是后来随着网页,Chrome的UI界面都选择采用GPU来绘制,这使得GPU成为浏览器普遍的需求。最后,Chrome在其多进程架构上也引入了GPU进程。
  • 网络进程:主要负责页面的网络资源加载,之前是作为一个模块运行在浏览器进程里面的,直至最近才独立出来,成为一个单独的进程。
  • 插件进程:主要是负责插件的运行,因为插件容易崩溃,所以需要通过插件进程来隔离,以保证插件进程崩溃不会对浏览器和页面造成影响。
    所以,打开一个网页,至少需要四个进程:1个网络进程,1个浏览器进程,1个GPU进程以及1个渲染进程。如果打开的页面有运行插件话,还需要再加上1个插件进程。
    虽然多进程模型提升了浏览器的稳定性,流畅性和安全性,但同样不可避免地带来了一些问题:
  • 更高的资源占用:因为每个进程都会包含公共基础结构的副本(如JavaScript运行环境),这就意味着浏览器会消耗更多的内存资源。
  • 跟复杂的体系架构:浏览器各模块之间耦合性高,扩展性差等问题,会导致现在的架构已经很难适应新的需求了。

3.浏览器渲染进程的线程

1)GUI渲染线程

负责渲染浏览器页面解析HTMLCSS构建DOM树构建CSSOM树构建渲染树绘制页面;当页面需要重绘或由于某种操作引发回流时,该线程就会执行。
注意:GUI渲染线程和JS引擎线程是互斥的,当JS引擎执行时GUI线程会被挂起,GUI更新会保存在一个队列中等到JS引擎空闲时立即被执行。

2)JS引擎线程

JS引擎线程也称为JS内核,负责处理Javascirpt脚本程序,解析JavaScript脚本,运行代码;JS引擎线程一直等待着任务队列中任务的到来,然后加以处理,一个Tab页中无论什么时候都只有一个JS引擎线程在运行JS程序;
注意:GUI渲染线程和JS引擎线程是互斥关系,所以如果JS执行的时间过长,会造成页面的渲染不连贯,导致页面渲染加载阻塞。

3)事件触发线程

事件触发线程属于浏览器而不是JS引擎,用来控制事件循环;当JS引擎执行代码如setTimeout时,(也可是来自浏览器内核的其他线程,如鼠标点击,AJAX异步请求等),会将对应任务添加到事件触发线程中;当对应的事件符合触发条件被触发时,该线程会把事件添加到待处理队列的队尾,等待JS引擎的处理。

4)定时器触发线程

定时器触发进程即setInterval与setTimeout所在线程;浏览器定时器计数器并不是由JS引擎计数的,因为JS引擎是单线程的,如果处于阻塞线程状态就会影响计时的准确性;因为使用单独线程来计时并触发定时器,计时完毕后,添加到事件队列中,等待JS引擎空闲后执行,所以定时器中的任务在设定的时间点不一定能够准时执行,定时器只是在指定时间点将任务添加到事件队列中;
注意:W3C在HTML标准中规定,定时器的定时时间不能小于4ms,如果小于4ms,则默认为4ms。

5)异步http请求线程

  1. XMLHttpRequest连接后通过浏览器新开一个线程请求
  2. 检查到状态变更时,如果设置有回调函数,异步线程就产生状态变更事件,将回调函数放入事件队列中,等待JS引擎空闲后执行。

4.如何实现浏览器内多个标签页之间的通信

实现多个标签页之间的通信,本质上都是通过中介模式来实现的。因为标签页之间没有办法直接通信,因此我们可以找一个中介者,让标签页和中介者进行通信,然后让这个中介者来进行消息的转发。

  • 使用websocket协议
  • 使用ShareWorker的方式
  • 使用localStorage的方式
  • 使用postMessage方法

5.对Service Worker的理解

Service Worker 是运行在浏览器背后的独立线程,一般可以用来实现缓存功能。使用Service Worker的话,传输协议必须为HTTPS。因为Service Worker中涉及到请求拦截,所以必须使用HTTPS协议来保障安全。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值