程序,进程和线程有什么区别?

程序,进程和线程有什么区别?

本文非原创,译自 www.backblaze.com/blog/whats-...

程序、进程和线程都是与软件执行相关术语,但你可能不清楚它们的真正含义。无论你是经验丰富的开发者、有抱负的爱好者,还是只是在打开电脑的任务管理器或Mac的活动监视器时想知道自己在看什么,学习这些术语对于理解计算机的工作方式至关重要。

什么是计算机程序?

什么是计算机程序? 程序是一系列编码指令,告诉计算机执行给定的任务。程序有很多种类型,包括内置在操作系统(OS)中的程序和用于完成特定任务的程序。一般来说,特定任务的程序被称为应用程序(或应用)。例如,你可能正在使用谷歌Chrome、Mozilla Firefox或苹果Safari等网页浏览器应用阅读这篇文章。其他常见的应用包括电子邮件客户端、文字处理器和游戏。

创建计算机程序的过程包括设计算法、用编程语言编写代码,然后编译或解释这些代码,将其转化为计算机可以执行的机器可读指令。

什么是编程语言?

编程语言是人类和计算机相互交流的方式。它们是一套规范化的规则和语法。

编译型与解释型程序

许多程序是用编译型语言编写的,并使用诸如C、C++、C#等编程语言创建。最终结果是一份代码的文本文件,它被编译成二进制形式以在计算机上运行(关于二进制形式的更多内容将在接下来的几段中介绍)。这个文本文件直接与你的计算机交流。尽管它们通常很快,但与解释型程序相比,它们也是固定的。这既有好处也有坏处:你可以更好地控制像内存管理这样的事情,但你依赖于平台,如果你需要在代码中更改某些内容,通常需要更长的时间来构建和测试。

还有另一种称为解释型程序的程序。它们需要一个额外的程序来接收你的程序指令,并将其翻译成计算机可以理解的代码。与编译型语言相比,这些类型的程序是平台独立的(你只需要找到一个不同的解释器,而不是编写一个全新的程序),并且它们通常占用的空间更小。一些最常见的解释型编程语言包括Python、PHP、JavaScript和Ruby。

最终,这两种类型的程序都以二进制形式运行并加载到内存中。程序必须以二进制运行,因为你的计算机CPU只能理解二进制指令。

什么是二进制代码?

二进制是计算机的基础语言。在最基本的层面上,计算机只使用两种电流状态------开和关。开状态用1表示,关状态用0表示。二进制与我们日常生活中使用的十进制不同。在十进制中,每个数字位置可以是从0到9的任何数字。在二进制系统中,每个位置要么是0,要么是1。

你可能听过一个关于程序员的笑话,"世界上只有10种人,懂二进制的人和不懂二进制的人"

程序通常以计算机可执行的形式存储在磁盘或非易失性存储器上。在此之前,它们使用如C、Lisp、Pascal或其他编程语言编写而成,这些语言包含逻辑、数据处理、设备管理、递归以及用户交互的指令。为了在计算机上运行,程序最终被编译成二进制形式(即由1和0组成)的代码文件。另一种类型的程序是"解释型语言",它们在运行时才被解释为可执行代码,而不是预先编译。常见的解释型语言包括Python、PHP、JavaScript和Ruby。

不管采用哪种方式,程序运行时都以二进制形式加载到内存中。因为计算机的CPU(中央处理单元)只理解二进制指令,所以当CPU运行程序时,程序需要转换成二进制形式。

二进制是计算机的原生语言,因为电子电路有两种基本状态:开或关,分别用0和1表示。我们平时使用的是基于10进制的通用编码系统,其中每个数位可以是从0到9的任意数字。而在二进制中,每个位置只能是0或1。

计算机程序如何存储和运行?

程序通常以可执行格式存储在磁盘或非易失性内存中。让我们详细解释一下这个过程。

在这个上下文中,我们会讨论计算机拥有两种类型的内存:易失性和非易失性。易失性内存是临时的,并实时处理。它更快、更容易访问,并提高了计算机的效率。然而,它不是永久的。当计算机关闭时,这种类型的内存会重置。

另一方面,非易失性内存除非被删除,否则是永久的。虽然访问速度较慢,但它可以存储更多信息。因此,它更适合用来存储程序。可执行格式的文件简单来说就是运行程序的文件。它可以由你的CPU(即处理器)直接运行。这些文件类型的例子包括Windows中的.exe和Mac中的.app。

程序运行需要哪些资源?

一旦程序以二进制形式加载到内存中,接下来会发生什么?

正在执行的程序需要从操作系统和内存中获取资源来运行。没有这些资源,你无法使用程序。幸运的是,你的操作系统自动管理分配资源给程序的工作。无论你使用的是Microsoft Windows、macOS、Linux、Android还是其他系统,你的操作系统总是在努力指导计算机的资源,以将你的程序转化为正在运行的过程。

除了操作系统和内存资源之外,每个程序都需要一些基本的资源。

  • 寄存器。它是计算机处理器(CPU)内部的一种非常快速的存储设备,它包含进程可能需要的数据,如指令、存储地址或其他数据。
  • 程序计数器。也称为指令指针,程序计数器扮演组织角色。它跟踪计算机在其程序序列中的位置。
  • 栈。栈是一种数据结构,用于存储有关计算机程序活动子程序的信息。它被用作进程的临时空间。它与为进程动态分配的内存区别开来,后者称为"堆"。

什么是计算机进程?

当程序连同其运行所需的所有资源一起加载到内存中时,它被称为进程。你可能会有一个单一程序的多个实例。在这种情况下,该运行程序的每个实例都是一个进程。

每个进程都有一个独立的内存地址空间。这个独立的内存地址很有用,因为它意味着进程独立运行,并与其他进程隔离。然而,进程不能直接访问其他进程中的共享数据。从一个进程切换到另一个进程需要一些时间(相对而言)来保存和加载寄存器、内存映射和其他资源。

拥有独立进程对用户来说很重要,因为这意味着一个进程不会损坏或破坏其他进程。如果一个单独的进程出现问题,你可以关闭那个程序并继续使用你的计算机。实际上,这意味着你可以结束一个功能失常的程序,并以最小的中断继续工作。

什么是线程?

最后一个问题是线程。线程是进程内的执行单元。一个进程可能只有一个线程,也可能有多个线程。

进程启动时,会收到内存和其他计算资源的分配。进程中的每个线程共享这些内存和资源。对于单线程进程,进程只包含一个线程。

在多线程进程中,进程包含多个线程,同时(更准确地说是"虚拟地"同时------你可以在下面关于并发的部分阅读更多相关内容)完成多项任务。

前面我们讨论了栈和堆,这是线程或进程可用的两种内存类型。区分这些内存类型很重要,因为每个线程都将拥有自己的栈。然而,一个进程中的所有线程将共享堆。

有些人将线程称为轻量级进程,因为它们有自己的栈,但可以访问共享数据。由于线程与进程和进程内的其他线程共享相同的地址空间,线程间的通信变得容易。缺点是,进程中一个功能失常的线程可能影响整个进程的可行性。

线程和进程的工作步骤

以下是你在计算机上打开应用程序时发生的事情:

  • 程序最初是编程代码的文本文件。
  • 程序被编译或解释为二进制形式。
  • 程序被加载到内存中。
  • 程序变成一个或多个正在运行的进程。进程通常相互独立。
  • 线程作为进程的子集存在。
  • 线程之间的通信比进程之间更容易。
  • 线程更容易受到同一进程中其他线程引起的问题的影响。
对比 进程 线程
定义 拥有自己内存空间的独立程序。 进程的轻量、较小单位,共享内存。
创建开销 由于有独立内存空间,开销较高。 由于共享相同的内存空间,开销较低。
隔离性 进程彼此隔离。 线程共享相同的内存空间。
资源分配 每个进程都有自己的系统资源集。 线程在同一进程中共享资源。
独立性 进程相互之间更加独立。 线程在进程内相互依赖。
故障影响 一个进程的故障不会直接影响其他进程。 一个线程的故障可能影响同一进程中的其他线程。
同步需求 由于进程是隔离的,同步需求较少。 由于资源共享,需要仔细同步。
示例用途 运行多个独立应用程序。 在单个应用程序内进行多线程处理,以实现并行性。
内存使用 通常消耗更多内存。 与进程相比,消耗较少的内存。

关于并发和并行

你可能会问,进程或线程是否可以同时运行。答案是:这取决于具体情况。在拥有多个处理器或CPU核心的环境中,同时执行多个进程或线程是可行的。然而,在单处理器系统上,真正的同时执行是不可能的。在这些情况下,会采用进程调度算法来在运行的进程或线程之间共享CPU,从而创造出并行执行的假象。每个任务被分配一个"时间片",任务之间的快速切换通常对用户来说是不可察觉的,看起来就像是同时发生的。术语"并行性"(指真正的同时执行)和"并发性"(指随时间交错进行的进程以模拟同时执行)区分了这两种操作模式,无论是真正的同时进行还是近似模拟。

  • 并发(Concurrency) :在单处理器或多处理器系统中,通过进程或线程的交错执行(即它们在不同时间点运行),来模拟多任务同时进行。在单处理器系统中,由于只能在任一时刻执行一个任务,因此并发是实现多任务处理的唯一方式。 并行(Parallelism) :在多处理器系统中,不同的进程或线程可以在相同的时间真正同时执行。这利用了多核或多处理器的硬件优势,以实现更高效的任务处理。

Google Chrome 如何使用进程和线程

为了说明进程和线程的影响,我们来考虑一个实际例子:许多人使用的程序------Google Chrome 浏览器。

在设计 Chrome 浏览器时,Google 面临了几个重要的决策。例如,Chrome 应该如何处理在使用浏览器时经常同时发生的许多不同任务的问题?每个浏览器窗口(或标签页)可能会与互联网上的多个服务器通信,下载音频、视频、文本和其他资源。此外,许多用户大多数时间都会打开 10 到 20 个(或更多)浏览器标签页,每个标签页可能执行多个任务。

Google 必须决定如何处理所有这些任务。他们选择将 Chrome 中的每个浏览器窗口作为一个独立的进程运行,而不是作为一个或多个线程。这种方法带来了几个好处。

  • 将每个窗口作为一个进程运行,可以保护整个应用程序免受程序错误和故障的影响。
  • 将 JavaScript 程序隔离在一个进程中,可以防止它占用过多的 CPU 时间和内存,导致整个浏览器变得无响应。

话虽如此,Google 的设计决策也有权衡成本。为每个浏览器窗口启动一个新进程,与使用线程相比,在内存和资源上有更高的固定成本。他们赌的是,他们的方法最终会导致整体上的内存消耗较少。

在内存较低时,使用进程而不是线程可以提供更好的内存使用效率。实际上,一个不活跃的浏览器窗口被视为较低优先级。这意味着当需要内存用于其他进程时,操作系统可能会将其交换到磁盘。如果窗口是线程化的,就更难有效分配内存,最终导致计算机性能下降。

想要了解更多关于 Google 对 Chrome 的设计决策,可以查阅 Chromium 博客Chrome 介绍漫画

下面的屏幕截图显示了在一台打开了许多标签页的 MacBook Air 上运行的 Google Chrome 进程。你可以看到,一些 Chrome 进程正在使用相当多的 CPU 时间和资源(例如,顶部的一个正在使用 44 个线程),而其他一些则使用较少。

Mac 上的"活动监视器"(或 Windows 中的"任务管理器")可以成为优化计算机性能或排查问题的有价值助手。如果你的计算机运行缓慢,或者某个程序或浏览器窗口长时间无响应,你可以使用系统监视器检查其状态。

在某些情况下,你可能会看到某个进程被标记为"无响应"。尝试退出那个进程,看看你的系统是否运行得更好。如果某个应用程序占用了大量内存,你可能会考虑选择另一个能完成相同任务的应用程序。

相关推荐
别说我什么都不会11 小时前
鸿蒙轻内核M核源码分析系列十二 事件Event
操作系统·harmonyos
qq_437896431 天前
动态内存分配算法对比:最先适应、最优适应、最坏适应与邻近适应
操作系统
别说我什么都不会1 天前
鸿蒙轻内核M核源码分析系列十一 (2)信号量Semaphore
操作系统·harmonyos
别说我什么都不会2 天前
鸿蒙轻内核M核源码分析系列十 软件定时器Swtmr
操作系统·harmonyos
别说我什么都不会2 天前
鸿蒙轻内核M核源码分析系列九 互斥锁Mutex
操作系统·harmonyos
别说我什么都不会3 天前
鸿蒙轻内核M核源码分析系列七 动态内存Dynamic Memory
操作系统·harmonyos
别说我什么都不会3 天前
鸿蒙轻内核M核源码分析系列六 任务及任务调度(3)任务调度模块
操作系统·harmonyos
徐徐同学3 天前
【操作系统】操作系统概述
操作系统·计算机系统
守望时空334 天前
Linux内核升级指南
linux·操作系统
塞尔维亚大汉4 天前
OpenHarmony(鸿蒙南向开发)——小型系统内核(LiteOS-A)【用户态内存调测】
操作系统·harmonyos