浏览器进程

199 阅读9分钟

浏览器中的进程 & 线程

进程 & 线程概念、区别

当我们启动某个程序时,操作系统会给该程序创建一块内存(当程序关闭时,该内存空间就会被回收),用来存放代码、运行中的数据和一个执行任务的主线程,这样的一个运行环境就叫进程

线程是依附于进程的,在进程中使用多线程并行处理能提升运算效率,进程将任务分成很多细小的任务,再创建多个线程,在里面并行分别执行

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

  • 进程与进程之间完全隔离,互不干扰,一个进程崩溃不会影响其他进程,避免一个进程出错影响整个程序
  • 进程与进程之间需要传递某些数据的话,就需要通过进程通信管道IPC来传递
  • 一个进程中可以并发多个线程,每个线程并行执行不同的任务
  • 一个进程中的任意一个线程执行出错,会导致这个进程崩溃
  • 同一进程下的线程之间可以直接通信和共享数据
  • 当一个进程关闭之后,操作系统会回收该进程的内存空间

基本概念

  • 进程:是对运行时程序的封装,是系统进行资源调度&分配的基本单位,实现了操作系统的并发;
  • 线程:是进程的子任务,是CPU调度 & 分派的基本单位,用于保证程序的实时性,实现进程内部的并发; 线程是操作系统可识别的最小执行和调度单位。 每个线程都独自占用一个虚拟处理器:肚子的寄存器组,指令计数器&处理器状态。 每个线程完成不同的任务,但是共享同一个地址空间(也就是同样的动态内存、映射文件,目标代码等等),打开的文件队列和其他内核资源。

区别

  1. 一个线程只能属于一个进程,而一个进程可以有多个线程,且至少有一个线程。 线程依赖于进程而存在。
  2. 进程在执行过程中拥有独立的内存单元,而多个线程共享进程的内存。 资源是分配给进程的,同一进程的所有线程共享该进程的所有资源。同一个进程中的很个线程共享代码段(代码&常量),数据段(全局变量&静态变量),扩展段(堆存储)。但是每个线程拥有自己的栈段,栈段又叫运行时段,用来存放所有局部变量 & 临时变量。
  3. 进程是资源分配的最小单位,线程是 CPU 调度的最小单位
  4. 进程切换的开销大于线程切换的开销。 系统开销:在创建 or 撤销进程时,系统都要为其分配 & 回收资源,如内存空间、I/O设备等。因此,操作系统所付出的开销将显著大于在创建 or 撤销线程时的开销。类似地,在进程切换时,涉及到整个当前进程 CPU 环境的保存以及新被调度运行的进程的 CPU 环境的设置;而线程切换只需保存和设置少量寄存器的内容,并不涉及存储器管理方面的操作。
  5. 通信:进程间通信;线程间通信
  6. 进程编程调试简单可靠性高,但是创建销毁的开销大;线程开销小,切换速度快,但是编程调试相对复杂。
  7. 进程间不会相互影响;但如果一个线程挂掉,将导致整个进程挂掉。
  8. 进程适用于多核、多机分布;线程适用于多核。

僵尸进程 & 孤儿进程

孤儿进程:父进程退出了,但是他的一个或多个子进程还在运行,这些子进程就是孤儿进程;孤儿进程都将被 init进程收养,并负责这些孤儿进程的以后。

僵尸进程:就是子进程比父进程先结束,而父进程还没有释放子进程占用的资源,那么子进程的描述还留在系统中,这种进程就是僵尸进程。

进程间通信的方式:

进程间通信主要包括管道、系统 IPC(包括消息队列、信号量、信号、共享内存等)、套接字 socket。

1. 管道通信

在操作系统内核中开辟一段缓冲区,进程1就可以将需要交互的数据拷贝到这个缓冲区中,进程2可从这个缓冲区中读取数据。

1.1 匿名管道/PIPE
  • 半双工,具有固定的读端 & 写端;
  • 只能用于具有亲缘关系的进程之间的通信(父子进程 or 兄弟进程之间);
  • 可以将它看成是一种特殊文件,对于它的读写也可以使用 read、write 函数,但它不是普通的文件,并不属于其他任何文件系统,并且只存在于内存中。
1.2 命名管道/FIFO
  • 可以在不具有亲缘关系的进程之间交换数据;
  • 有路径名与之相关联,其以一种特殊设备文件形式存在于文件系统中

2. 系统IPC

2.1 消息队列

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

特点:

  • 是面向记录的,其中的消息具有特定的格式以及特定的优先级;
  • 独立于发送与接收进程。当进程终止时,消息队列及其内容并不会删除;
  • 可以实现消息的随机查询,消息不一定要以先进先出的次序读取,也可以按消息的类型读取。
2.2 信号量 semaphore

是一个计数器,可以用来控制多个进程对共享资源的访问; 用于实现进程间的互斥与同步,而不是用于存储进程间通信数据。 特点:

  • 信号量用于进程间同步,若要在进程间传递数据需要结合共享内存;
  • 信号量基于操作系统的PV操作,程序对信号量的操作都是原子操作;
  • 每次对信号量的PV操作不仅限于对信号量值加1 or 减1,而且可以加减任意正整数;
  • 支持信号量组。
2.3 信号量通信 signal

信号是一种比较复杂的通信方式,用于通知接收进程某个事件已经发生。

比如信号量初始值是 1,进程 1 来访问一块内存的时候,就把信号量置为 0,然后进程 2 想访问的时候会看到信号量为 0,就知道有其他进程在访问,所以进程 2 就不会访问了。

2.4 共享内存/shared memory

就是映射一段能被其他进程访问的内存,由1个进程创建,但多个进程都可以访问。

使得多个进程可以访问同一块内存空间,不同进程可以及时看到对方进程中对刚想内存中数据的更新。这种方式需要依靠某种同步操作,如互斥锁&信号量等;

特点:

  • 共享内存是最快的一种 IPC,因为进程是直接对内存进行存取;
  • 因为多个进程可以同时操作,所以需要进行同步;
  • 信号量+共享内存通常结合在一起使用,信号量用来同步对共享内存的访问。

3. 套接字/socket

socket 也是一种进程间的通信机制,与其他通信机制不同的是,它可以用于不同主机之间的进程通信,比如 发起 http 请求,服务器返回数据。

chrome浏览器的进程 & 线程

  • 1个浏览器主进程:负责控制浏览器除标签页以外的界面,包括地址栏、书签、前进后退按钮等,以及负责与其他进程的协调工作,同时提供存储功能;
  • 1个GPU进程:负责整个浏览器界面的渲染;
  • 1个网络进程:负责发起和接收网络请求;
  • 多个渲染进程:负责控制显示tab标签页的所有内容,核心任务是将 html、css、js 转换为用户可以与之交互的网页,排版引擎blink & js运行引擎 v8 都是运行在该进程中,默认情况下 chrome 会为每个 tab标签页创建一个渲染进程;
  • 多个插件进程:负责插件的运行,因为插件可能崩溃,所以需要通过插件进程来隔离,来保证插件崩溃也不会对浏览器和页面造成影响;

浏览器呈现出页面的过程中,大部分工作都是在渲染进程中完成,其中有很多线程:

  • GUI 渲染线程:负责渲染页面,解析 html、css,构建 DOM树、CSSOM树、渲染树 & 绘制页面,重排重绘也是在该线程执行;
  • JS引擎线程:一个 tab页中只有一个 JS引擎线程(单线程),负责解析 & 执行 js。其与 GUI 渲染线程不能同时执行,必须一个一个来,如果 JS 执行时间过长就会阻塞掉帧
  • 计时器线程:负责 setInterval & setTimeOut的计时器工作;
  • 异步 HTTP 请求线程:XMLHttpRequest 连接后,浏览器开的线程,比如请求有回调函数,异步线程就会将回调函数加入事件队列,等待 JS引擎空闲时执行;
  • 事件触发线程:主要用来控制事件循环,比如 JS 执行遇到计时器,AJAX异步请求等,就会将独赢任务添加到事件触发线程中,在对应事件符合触发条件时,就把事件添加到待处理队列的队尾,等待JS引擎处理;

浏览器缓存

参考文章

深入理解浏览器中的进程与线程 进程和线程的概念、区别及进程线程间通信