浏览器进程与线程

一、浏览器进程与线程

1、进程与线程的概念?

  • 进程是CPU中最小的资源单位;线程是CPU中最小的调度单位。
  • 进程在应用上是一个程序,代表了CPU运行指令,加载保存上下文所需的时间;线程是进程中更小的单位,执行一段指令所需的时间

进程是一个程序的运行实例。启动程序时,一个操作系统为一个程序创建一个虚拟内存,用来存放代码,运行中的数据和一个运行中的主线程,这个运行环境就是进程。(虚拟内存解决了用户对硬件的无限需求和有限硬件资源之间矛盾。从操作系统看,虚拟内存是交换文件;在处理器方面看,虚拟内存是虚拟地址空间)

进程与线程之间关系有4个特点:

  • 进程中只要一个线程报错,进程就会报错
  • 进程结束,操作系统会回收所占内存,线程也会结束,即使进程中的线程有内存泄漏,也会直接回收
  • 进程之间的内容相互隔离,每个进程都是独立的,即使有一个进程报错也不会影响其他进程,所以需要进程间互相通信
  • 进程中的线程互相共享进程中的数据

2、进程与线程的区别?

  • 进程可以看作一个独立应用,线程不行
  • 单位:进程是CPU最小的资源单位(是能拥有资源和独立运行的最小单位);线程是CPU最小的调度单位(线程是运行在进程上的一个程序运行单位,一个进程可以有多个线程)
  • 通信:进程之间通信需要根据进程通信方式(见下文);线程共享进程中的数据
  • 切换开销:进程切换的开销远远大于线程,线程切换不会引起进程切换,A进程中的线程切换到B进程中的线程,会引起进程切换
  • 系统开销 :撤销或创建进程时,系统会回收或重新分配资源,如内存,I/O等,进程开销远大于撤销或创建线程的开销。进程之间切换会涉及到:执行进程的CPU环境、各种状态的保存、新进程状态的设置等 ;线程之间切换只会涉及到 保存和设置少量寄存器

3、chrome浏览器中进程有哪些?

总共有五种:

1. 一个浏览器进程

主要进行界面显示,用户交互,子进程管理,提供存储等功能

2. 多个渲染进程

主要是对html、css、js等转换为用户能交互的页面,排版引擎blink和js引擎V8都是运行在这个进程,默认情况下,浏览器会为每个Tab标签创建一个渲染进程。出于安全考虑,渲染进程都是运行在沙箱模式下。

3. 一个GPU进程

以前的GPU进程初衷是为了3D CSS效果,后来UI界面也直接使用GPU绘制,浏览器就引入了GPU进程

4. 一个网络线程

主要是用于网络加载,以前是浏览器进程程中的一个模块,后来独立出来称为网络进程

5. 多个插件进程

用来执行插件,因为插件容易崩溃,所以使用插件进程隔离,防止插件对浏览器和页面造成其他影响

多进程模型提升了浏览器的稳定性、流畅性和安全性,但也带来了一些问题:

  • 更高的资源占用:因为每个进程都会包含公共基础结构(如 JavaScript 运行环境),这就意味着浏览器会消耗更多的内存资源。
  • 更复杂的体系架构:浏览器各模块之间耦合性高、扩展性差等问题,会导致现在的架构已经很难适应新的需求了。

4、浏览器渲染进程的线程有哪些?

总共有五种:

1. GUI渲染线程

GUI渲染进程是将HTML渲染为DOM树,将CSS渲染为CSSOM树,进行页面的渲染与绘制;当发生重绘回流(重排) 时会触发这一线程

GUI渲染线程与JS引擎线程是互斥的,等JS线程运行时,GUI会挂载;GUI更新会被保存到一个队列中,等JS引擎空闲时立即执行

2. JS引擎线程

JS引擎线程JS内核,是执行脚本,解析JS脚本,运行代码;JS引擎一直等待任务队列中的任务到来,然后进行处理,一个Tab页只能有一个JS引擎线程运行js程序,最后所有的任务都会汇总到JS引擎线程中执行

JS引擎线程与GUI渲染线程互斥,所以如果JS运行时间很长,会造成页面渲染阻塞

3. 事件触发线程

事件触发线程是浏览器触发的,不是js引擎,用来控制事件循环。当js引擎处理代码块时,例如setTimeout或者浏览器内核其他线程如鼠标点击,异步请求等,会将事件存放到待处理的队尾,等js引擎处理

因为js是单线程,所以这些待处理的事件都要等js引擎空闲时处理

4. 定时器触发线程

定时器触发线程单独放在一个线程中,定时计数器不是通过JS引擎处理的,因为js是单线程,如果放到js引擎中,阻塞时就会影响计数的准确性。计数器是放到定时器触发线程中,等时间到后,添加到事件队列中,等js引擎空闲时处理

W3C 在 HTML 标准中规定,定时器的定时时间不能小于 4ms,如果是小于 4ms,则默认为 4ms。

5. 异步http请求线程

XMLHttpRequest 连接后通过浏览器新开一个线程请求;检测到状态变更时,如果设有回调函数,异步线程就会产生状态变更事件,将回调函数放入到事件队列中,等js引擎空闲时处理

5、进程之间的通信方式?

1. 管道通信

管道通信是进程中最基本的通信方式。管道是操作系统在内核中开辟一段缓冲区,进程A将需要交换的数据拷贝到缓冲区,进程B就可以读取了。

管道通信特点:

  • 进程之间有血缘关系
  • 只能单向通信
  • 管道中是同步机制
  • 依赖于文件系统
  • 生命周期随进程
  • 面向字节流的服务
2. 消息队列通信

消息队列就是一个消息的列表。用户可以在队列中添加信息,读取信息等。消息队列提供了一个进程向另一个进程发送数据块的方法,每个数据库有一个类型,接收进程可以接受一个含有不同类型的数据结构。

缺点是:消息队列中的数据块有最大长度限制。如果频繁的发生通信行为,需要频繁的读取消息队列中的数据到内存,相当于从一个进程拷贝到另一个进程,需要花费时间。

3. 共享内存通信

共享内存通信是一个进程创建,其他多个进程可以访问的共享内存。共享内存通信是专门设置的其他通信效率低的时候使用,优点是最快的IPC(InterProcess Communication 不同进程交换数据)方式, 缺点是多个进程竞争内存的问题,所以经常与信号量通信方式一起使用。

4. 信号量通信

信号量通信相当于一个计数器,实现进程间的互斥与同步。在共享内存中,如A进程访问内存1时,信号量的值由1变为0,等B进程访问共享内存1时,就不能访问

5. 信号通信

信号通信是Unix系统最古老的通信方式之一,操作系统通过信号来通知预先设定好的事件

6. 套接字通信

上边的管道通信,消息队列通信,共享内存通信,信号量通信都是多个进程在一台主机上进行通信。那么不同主机上的进程进行通信,需要使用Socket进行通信,例如浏览器发送http请求,服务器返回对应的数据就是Socket通信。

6、在浏览器中多个标签之间如何通信?

在浏览器中,多个标签页之间无法直接通信,本质上是通过中介者模式进行通信,通过中介者转发

1. 通过webSocket进行通信

webSocket可以传递到服务器上,所以可以使用将一个标签内容传递到服务器上,等另一个标签改变的时候,通过服务器传送给标签

2. 通过shareWorker方式

shareWorker会在页面存在的生命周期中存在唯一一个线程,在多个页面中也是这唯一的一个线程。这个时候共享线程可以当作一个中介者,使用共享线程进行转发

3. 通过localStorage

可以在一个标签页对localStorage的事件进行监听,当另一个标签页修改数据时,就可以通过监听事件来获取数据,这时候localStorage就是中介者的角色

4. postMessage

能够获得对应标签页的引用时,可以使用postMessage进行转发

7、对Service Worker的理解?

Service Worker主要是创建有效的离线体验,当点击离线后,会拦截网络请求,并根据网络是否可用来采取适当的动作、更新来自服务器的资源,可以细粒度的缓存资源。

Service worker 运行在 worker 上下文:因此它无法访问 DOM,相对于驱动应用的主 JavaScript 线程,它运行在其他线程中,所以不会造成阻塞。它被设计为完全异步;因此,同步 XHRWeb Storage 不能在 service worker 中使用。Service worker 只能由 HTTPS 承载

8、死锁产生的原因,如何解决死锁?

死锁是多个进程因争夺资源而产生的僵局,这种僵局,没有外力作用,将无法再向前推进。

系统资源分为:

  • 不可剥夺资源:只要分配了资源,只能进程完毕后再进行下一个进程,不能强制收回。如打印机,磁带机等
  • 可剥夺资源:进程分配了资源,可以被其他进程剥夺或者强制收回。CPU和主存是可剥夺资源

产生死锁的原因:

  • 竞争资源:

    • 竞争不可剥夺资源:例如系统中只有一台打印机,正在使用,另一个进程要求打印,就会阻塞
    • 竞争临时资源:临时资源包括硬件中断、信号、消息、缓冲区内的消息等,通常消息通信顺序进行不当,则会产生死锁
  • 进程间推进顺序非法:

    • 若P1保持了资源R1,P2保持了资源R2,系统处于不安全状态,因为这两个进程再向前推进,便可能发生死锁。例如,当P1运行到P1:Request(R2)时,将因R2已被P2占用而阻塞;当P2运行到P2:Request(R1)时,也将因R1已被P1占用而阻塞,于是发生进程死锁

产生死锁的必要条件:

  • 在一段时间内某资源仅为一进程所占用
  • 保持不放:当进程因请求资源而阻塞时,对已获得的资源保持不放
  • 不能剥夺资源:进程在资源未使用完之前,不能剥夺,只能使用完自己释放
  • 环路等待:在发生死锁时,必然存在一个进程------资源的环形链

预防死锁方法:

  • 一次性分配资源:这样就不会再有请求
  • 破坏保持不放:只要有一个资源得不到分配,也不给这个进程分配其他的资源
  • 破坏不能剥夺资源:当某进程获得了部分资源,但得不到其它资源,则释放已占有的资源
  • 破坏环路等待:系统给每类资源赋予一个编号,每一个进程按编号递增的顺序请求资源,释放则相反

9、僵尸进程和孤儿进程是什么?

1. 僵尸进程

僵尸进程是:父进程和子进程,子进程比父进程先结束,父进程没有释放子进程的占用资源,子进程的进程仍然在系统中,这种被称为僵尸进程。

2. 孤儿进程

孤儿进程是:父进程和子进程,父进程退出了,而它的一个或多个进程还在进行,这些子进程被称为孤儿进程。孤儿进程由init进程(进程1号)收养,并对他们完成状态收集工作。

相关推荐
前端小巷子2 分钟前
web从输入网址到页面加载完成
前端·面试·浏览器
江城开朗的豌豆2 分钟前
Vue路由动态生成秘籍:让你的链接'活'起来!
前端·javascript·vue.js
晓得迷路了3 分钟前
栗子前端技术周刊第 88 期 - Apache ECharts 6.0 beta、Deno 2.4、Astro 5.11...
前端·javascript·echarts
江城开朗的豌豆8 分钟前
在写vue公用组件的时候,怎么提高可配置性
前端·javascript·vue.js
江城开朗的豌豆9 分钟前
Vue路由跳转的N种姿势,总有一种适合你!
前端·javascript·vue.js
江城开朗的豌豆9 分钟前
Vue路由玩法大揭秘:三种路由模式你Pick谁?
前端·javascript·vue.js
江城开朗的豌豆10 分钟前
Vue路由守卫全攻略:给页面访问装上'安检门'
前端·javascript·vue.js
小磊哥er17 分钟前
【前端工程化】前端组件模版构建那些事
前端
前端 贾公子18 分钟前
monorepo + Turborepo --- 开发应用程序
java·前端·javascript
江城开朗的豌豆22 分钟前
Vue路由传参避坑指南:params和query的那些猫腻
前端·javascript·vue.js