用这么久的浏览器你连他的进程都不知道?

485 阅读11分钟

线程和进程

进程是操作系统分配资源的最小单位

进程是操作系统中一个正在执行的程序的实例。它包含了程序代码、数据、栈、堆以及程序计数器等所有资源,并且每个进程都是操作系统调度和管理的基本单位。

特点:

  1. 独立性:进程是独立运行的,每个进程都有自己的地址空间(内存),并且与其他进程隔离。一个进程的崩溃不会直接影响其他进程。
  2. 资源拥有者:进程拥有操作系统分配给它的资源(如CPU时间、内存、文件句柄等)。
  3. 进程间通信(IPC) :进程之间不能直接共享数据,因此需要使用某些机制来进行通信,如管道、消息队列、共享内存、套接字等。

进程的生命周期:

  • 创建:操作系统为程序分配内存、资源,并启动程序的执行。
  • 执行:进程开始执行程序代码。
  • 等待/阻塞:进程可能因等待某些事件(如I/O操作)而进入阻塞状态。
  • 终止:进程执行完毕或被强制终止后,操作系统回收其占用的资源。

线程是cpu调度的基本单位

线程是进程中的一个执行单元,是CPU调度的基本单位。一个进程可以有多个线程,这些线程共享该进程的资源(如内存、文件句柄等),但每个线程都有自己的执行栈和程序计数器。

特点:

  1. 共享资源:同一进程中的多个线程共享进程的资源,包括内存空间、全局变量等。
  2. 轻量级:相对于进程,线程的创建和销毁开销较小,因为线程之间共享资源,因此切换线程的开销较小。
  3. 并行执行:同一进程中的多个线程可以并行执行,或者在多核CPU上并行运行,以提高程序的执行效率。

线程的生命周期:

  • 创建:线程被创建时,由操作系统分配资源(如栈空间)。
  • 执行:线程开始执行代码,使用该进程的资源。
  • 等待/阻塞:线程可能因等待某些事件(如I/O操作)而进入阻塞状态。
  • 终止:线程执行完成后,操作系统回收其资源。

现代操作系统采用分时复用技术来处理多任务,会迅速的并行切换任务,从用户看,这些应用好像在同时运行,不过之前打开的应用也不会停止运行。不过打开的应用过多,电脑可能出现运行缓慢的现象。

我们用QQ来给大家举个例子来区分进程和线程。

假设场景:你正在使用 QQ,并且进行以下操作:

  • 发送消息
  • 接收消息
  • 查看联系人列表
  • 语音通话

在使用QQ时,整个QQ应用程序通常会以一个进程的形式运行。这个进程负责管理应用程序的所有资源和任务。比如:

  • QQ的主窗口(显示联系人、聊天记录等)属于这个进程。
  • 当你登录QQ时,操作系统会为QQ分配一个进程,管理它所需的所有资源,比如内存、文件、网络连接等。

因此,QQ应用本身就是一个进程,它在运行时拥有自己独立的内存空间和资源。

一个进程(比如QQ进程)可以包含多个线程,每个线程负责执行不同的任务。QQ应用中的不同功能通常是由不同的线程来处理的,这样就能提高应用的响应速度,避免出现卡顿。以下是一些线程的例子:

  • 发送消息线程:当你点击“发送消息”按钮时,QQ需要将消息发送到服务器。这时,QQ可能会启动一个专门的线程来处理消息的发送,避免主线程(即界面线程)被阻塞。
  • 接收消息线程:QQ还需要保持与服务器的连接,以便接收你朋友发来的新消息。这个任务会由一个独立的线程来处理,确保你能够即时收到消息,而不会因为发送消息时卡住界面。
  • 聊天界面线程:这个线程主要负责处理用户界面相关的操作,比如显示聊天记录、滚动聊天窗口、点击联系人等。它与其他线程协作,保证你能够流畅地操作应用。
  • 语音通话线程:如果你正在进行语音通话,可能会有一个独立的线程负责处理语音数据的采集、压缩、传输等工作,而另一个线程负责接收和播放语音。这样能避免语音通话的处理和聊天界面渲染产生冲突。

如果QQ只用一个线程来处理所有操作,那当你发送消息时,界面就会被锁死,无法进行其他操作(如查看联系人、滚动聊天记录)。而如果QQ使用多个线程,每个线程独立处理不同的任务,应用就能保持响应速度,提升用户体验。

  • 并发:多个线程可以并发执行不同的任务,比如同时接收和发送消息,刷新界面等等。即使是在单核CPU上,操作系统也会交替执行这些任务,给人一种“并行”工作的感觉。
  • 资源共享:多个线程共享进程的内存和数据,这样它们之间可以很容易地共享信息,比如聊天记录、联系人列表等。

当然,在实际情况中QQ也不只是一个进程。

比如我有下载功能,我就要使用另一个进程。那为什么下载任务就要用另一个进程而不用线程呢?

  • 线程:多个线程属于同一个进程,它们共享进程的内存空间、资源和数据。这种共享带来了高效的资源利用,但也可能会引起线程之间的干扰(比如内存竞争、死锁等问题)。因此,线程之间需要小心协调。
  • 进程:每个进程有自己独立的内存空间和资源,进程之间的资源是完全隔离的,互不干扰。虽然进程间通信(IPC)可能比线程间的通信复杂,但它避免了多线程中可能出现的问题,特别是在资源和数据隔离方面。

因此,对于像下载这类需要独立管理资源(如网络连接、文件存储等)的任务,使用一个单独的进程是更加合适的。这样即使下载过程出错,也不会直接影响到主应用程序(QQ的聊天界面等)。同时,下载进程可以通过操作系统的资源管理来独立运行,避免了资源冲突。

浏览器的小知识

Chrome是目前全球使用最广泛的浏览器,其成功的背后有许多因素。从最早的Internet Explorer(IE)到微软的Edge浏览器,再到如今的Chrome,市场的竞争格局发生了剧变。Chrome凭借其高性能、快速启动、良好的兼容性以及强大的开发者工具,逐渐超越了IE,成为了市场的主流浏览器。尤其在国内,许多所谓的“本地浏览器”实际上都是基于Chrome内核(如360浏览器、腾讯浏览器等)。

2. 内核的优势:

IE与Chrome在技术上有显著差异。IE使用的是Trident内核,而Chrome则基于Webkit内核,并在其基础上开发了Blink内核。IE的Trident内核与Web标准的兼容性较差,尤其是在布局模型(如box-sizing)方面,与现代Web标准存在较大差异。相比之下,Webkit(后来升级为Blink)内核支持更好的兼容性,使得Web开发者能够更容易地进行跨浏览器开发。

对于现代Web应用来说,浏览器的内核决定了代码的渲染效率和兼容性。Webkit内核由苹果最初开发,Google基于Webkit开源了Chromium项目,并将其作为Chrome的基础。Chromium不仅是开源的,还吸引了大量开发者和公司贡献代码,推动了浏览器的快速发展。

3. V8引擎:

Chrome浏览器还内置了Google开发的V8 JavaScript引擎,它是一个高效的JavaScript引擎,极大提高了JavaScript的执行效率。在浏览器中,JavaScript是非常关键的技术,负责许多动态交互和数据处理任务。V8引擎通过JIT(即时编译)和垃圾回收机制优化了性能,使得页面加载速度和响应时间大大缩短。

在 IE6 及之前的版本中,盒子模型的计算存在问题。当开发者设置元素的 width 时,Trident 引擎 会将 paddingborder 的宽度也算入 width 的计算中,这导致了布局问题。这种实现方式被称为“传统盒模型”或“IE 盒子模型”。

举个例子:

div {
    width: 200px;
    padding: 20px;
    border: 10px solid black;
}

在 IE6 中,div 的实际宽度200px + 20px(padding-left) + 20px(padding-right) + 10px(border-left) + 10px(border-right),所以总宽度为 200px,而不是 200px 加上内边距和边框。这样会导致网页布局和设计出现意外的偏移。

现代的 CSS 盒子模型规范采用了不同的计算方式,即 content-box 模式。该模式下,widthheight 只包括内容区域的大小,内边距(padding)和边框(border)是添加在内容区域外的。因此,如果开发者设置元素的宽度为 200px,那么总宽度就是 200px,加上内边距和边框。

image.png

浏览器的多进程

我们首先打开chrome 浏览器内置的任务管理器查看一下进程

image.png

我们发现里面有很多的进程,甚至每一个标签页都是一个进程(。例如,如果一个Tab页出现问题,Chrome可以只关闭该Tab的渲染进程,而不会影响到其他Tab页。) 下面介绍介绍浏览器的几个重要进程

  • 浏览器主进程: 该进程负责管理浏览器的用户界面(UI),处理用户交互,管理其他子进程的通信(IPC),并负责存储功能(如cookie、localStorage等)。浏览器主进程还负责与操作系统的交互,确保浏览器的顺畅运行。
  • 渲染进程: 渲染进程的核心任务是将HTML、CSS和JavaScript转换为用户可以交互的网页内容。Chrome的渲染进程基于Webkit/Blink引擎和V8引擎,处理JavaScript执行、页面渲染、事件响应等任务。每个Tab页默认会有一个独立的渲染进程,以提高浏览器的性能和稳定性。
  • 插件进程: 对于Flash、Chrome扩展等插件,Chrome会为其分配独立的进程,这样可以确保插件的安全性,不会直接影响浏览器的其他功能。
  • GPU进程: 用于处理复杂的图形渲染任务,特别是在需要进行3D绘制和动画渲染时,GPU进程能够将图形渲染交给显卡(GPU)进行加速,提高渲染性能。

浏览器启动过程

1. 用户启动浏览器

  • 用户点击浏览器图标(比如 Chrome、Firefox、Edge 等),操作系统接收到这个请求。
  • 操作系统启动一个新的浏览器进程,通常会创建一个新的 应用程序进程(在 Windows 上通常是 chrome.exe 或类似的进程名)。

2. 操作系统加载浏览器

  • 操作系统会找到浏览器的可执行文件,并将其加载到内存中。浏览器的可执行文件包含了启动程序、图形界面、核心库等必要的代码。
  • 操作系统会为浏览器进程分配资源(如内存、CPU 时间等)。

3. 浏览器初始化

  • 浏览器进程启动后,它会初始化自己的环境,包括加载用户的配置、插件和扩展、启动后台进程等。
  • 例如,Google Chrome 会启动多个进程来管理不同的功能:一个用于 UI 渲染,多个用于每个标签页和插件的隔离,另外还会启动一些后台进程(如网络请求和更新检查等)。

4. 浏览器进程创建多个子进程

  • 浏览器通常是多进程架构,每个打开的标签页可能会启动一个独立的子进程,这样可以提高稳定性和安全性。每个标签页会有自己的 渲染进程,它负责处理网页内容的渲染和脚本执行。
  • 此外,还有专门的 网络进程 来处理网络请求,GPU 进程 来加速渲染,甚至会有 插件进程(如果浏览器支持插件)。