进程和线程

本质上说,进程和线程都是 CPU 工作时间片的一个描述:

  • 进程描述了 CPU 在运行指令及加载和保存上下文所需的时间,放在应用上来说就代表了一个程序。

  • 线程是进程中的更小单位,描述了执行一段指令所需的时间

进程是资源分配的最小单位,线程是CPU调度的最小单位。

一个进程就是一个程序的运行实例。详细解释就是,启动一个程序的时候,操作系统会为该程序创建一块内存,用来存放代码、运行中的数据和一个执行任务的主线程,我们把这样的一个运行环境叫进程。进程是运行在虚拟内存上的,虚拟内存是用来解决用户对硬件资源的无限需求和有限的硬件资源之间的矛盾的。从操作系统角度来看,虚拟内存即交换文件;从处理器角度看,虚拟内存即虚拟地址空间

如果程序很多时,内存可能会不够,操作系统为每个进程提供一套独立的虚拟地址空间,从而使得同一块物理内存在不同的进程中可以对应到不同或相同的虚拟地址,变相的增加了程序可以使用的内存。

进程和线程之间的关系有以下四个特点:

  1. 进程中的任意一线程执行出错,都会导致整个进程的崩溃。

  2. 线程之间共享进程中的数据。

  3. 当一个进程关闭之后,操作系统会回收进程所占用的内存, 当一个进程退出时,操作系统会回收该进程所申请的所有资源;即使其中任意线程因为操作不当导致内存泄漏,当进程退出时,这些内存也会被正确回收。

  4. 进程之间的内容相互隔离。 进程隔离就是为了使操作系统中的进程互不干扰,每一个进程只能访问自己占有的数据,也就避免出现进程 A 写入数据到进程 B 的情况。正是因为进程之间的数据是严格隔离的,所以一个进程如果崩溃了,或者挂起了,是不会影响到其他进程的。如果进程之间需要进行数据的通信,这时候,就需要使用用于进程间通信的机制了

进程和线程的区别

  • 进程可以看做独立应用,线程不能

  • 资源:进程是cpu资源分配的最小单位(是能拥有资源和独立运行的最小单位);线程是cpu调度的最小单位(线程是建立在进程的基础上的一次程序运行单位,一个进程中可以有多个线程)。

  • 通信方面:线程间可以通过直接共享同一进程中的资源,而进程通信需要借助 进程间通信。

  • 调度:进程切换比线程切换的开销要大。线程是CPU调度的基本单位,线程的切换不会引起进程切换,但某个进程中的线程切换到另一个进程中的线程时,会引起进程切换。

  • 系统开销:由于创建或撤销进程时,系统都要为之分配或回收资源,如内存、I/O 等,其开销远大于创建或撤销线程时的开销。同理,在进行进程切换时,涉及当前执行进程 CPU 环境还有各种各样状态的保存及新调度进程状态的设置,而线程切换时只需保存和设置少量寄存器内容,开销较小。

进程之前的通信方式(IPC)

什么是 IPC 通信,如何建立 IPC 通信?什么场景下需要用到 IPC 通信?

IPC (Inter-process communication) ,即进程间通信技术,由于每个进程创建之后都有自己的独立地址空间,实现 IPC 的目的就是为了进程之间资源共享访问,实现 IPC 的方式有多种:管道、消息队列、信号量、Domain Socket,Node.js 通过 pipe来实现。

管道通信

管道是一种最基本的进程间通信机制。管道就是操作系统在内核中开辟的一段缓冲区,进程1可以将需要交互的数据拷贝到这段缓冲区,进程2就可以读取了。

管道的特点:

  • 只能单向通信

  • 只能血缘关系的进程进行通信

  • 依赖于文件系统

  • 生命周期随进程

  • 面向字节流的服务

  • 管道内部提供了同步机制

消息队列通信

消息队列就是一个消息的列表。用户可以在消息队列中添加消息、读取消息等。消息队列提供了一种从一个进程向另一个进程发送一个数据块的方法。 每个数据块都被认为含有一个类型,接收进程可以独立地接收含有不同类型的数据结构。可以通过发送消息来避免命名管道的同步和阻塞问题。但是消息队列与命名管道一样,每个数据块都有一个最大长度的限制。

使用消息队列进行进程间通信,可能会收到数据块最大长度的限制约束等,这也是这种通信方式的缺点。如果频繁的发生进程间的通信行为,那么进程需要频繁地读取队列中的数据到内存,相当于间接地从一个进程拷贝到另一个进程,这需要花费时间。

信号量通信

共享内存最大的问题就是多进程竞争内存的问题,就像类似于线程安全问题。我们可以使用信号量来解决这个问题。信号量的本质就是一个计数器,用来实现进程之间的互斥与同步。例如信号量的初始值是 1,然后 a 进程来访问内存1的时候,我们就把信号量的值设为 0,然后进程b 也要来访问内存1的时候,看到信号量的值为 0 就知道已经有进程在访问内存1了,这个时候进程 b 就会访问不了内存1。所以说,信号量也是进程之间的一种通信方式。

共享内存通信

共享内存就是映射一段能被其他进程所访问的内存,这段共享内存由一个进程创建,但多个进程都可以访问(使多个进程可以访问同一块内存空间)。共享内存是最快的 IPC 方式,它是针对其他进程间通信方式运行效率低而专门设计的。它往往与其他通信机制,如信号量,配合使用,来实现进程间的同步和通信。

套接字通信

上面说的共享内存、管道、信号量、消息队列,他们都是多个进程在一台主机之间的通信,那两个相隔几千里的进程能够进行通信吗?答是必须的,这个时候 Socket 这家伙就派上用场了,例如我们平时通过浏览器发起一个 http 请求,然后服务器给你返回对应的数据,这种就是采用 Socket 的通信方式了。

关于父进程与子进程是如何通信的

父进程在创建子进程之前会先去创建 IPC 通道并一直监听该通道,之后开始创建子进程并通过环境变量(NODECHANNELFD)的方式将 IPC 通道的文件描述符传递给子进程,子进程启动时根据传递的文件描述符去链接 IPC 通道,从而建立父子进程之间的通信机制

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

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

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

死锁

死锁是指两个或多个进程在执行的过程中,因为竞争资源而造成互相等待的现象,若无外力作用,它们都无法推进下去

系统中的资源可以分为两类:

  • 可剥夺资源,是指某进程在获得这类资源后,该资源可以再被其他进程或系统剥夺,CPU和主存均属于可剥夺性资源;

  • 不可剥夺资源,当系统把这类资源分配给某进程后,再不能强行收回,只能在进程用完后自行释放,如磁带机、打印机等。

如下以下几种场景:

  • 互相等待对方正在占有的资源

    举个例子,假设有P1,P2两个进程,都需要A和B两个资源,两个都等待另一个资源而不肯释放资源,就这样无限等待中,这就形成死锁。这只是死锁的一种情况,就是在等待对方时占有不可抢占的资源

  • 竞争可消耗资源引起死锁

    有P1,P2,P3三个进程,P1向P2发送消息并接受P3消息,P2向P3发送消息并接受P2消息,P3向P1发送消息并接受P2消息,如果设置是先接到消息后发送消息,则所有的消息都不能发送,也造成了死锁

  • 进程推进顺序不当引起死锁

    有进程P1,P2,都需要资源A,B,本来可以P1运行A,P1运行B,P2运行B,P2运行A,P2运行B,但顺序换了,P1运行A时P2运行B,容易引发死锁,属于第一种的资源抢占问题

产生死锁的必要条件:

  1. 互斥条件:一个资源每次只能被一个进程使用,即在一段时间内某资源仅为一个进程所使用。此时如果有其他进程请求该资源,则请求进程只能等待。

  2. 请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放

  3. 不可剥夺条件:进程未使用完的资源在未使用完毕之前,不能被其他进程强行夺走,即只能由获得该资源的进程自己来释放

  4. 循环等待条件:若干进程间形成首尾相接循环等待资源的关系。在发生死锁时必然存在一个进程等待队列{P1,P2,…,Pn},其中P1等待P2占有的资源,P2等待P3占有的资源,…,Pn等待P1占有的资源,形成一个进程等待环路,环路中每一个进程所占有的资源同时被另一个申请

这四个条件是死锁的必然条件,只要系统发生死锁,这些条件必然成立。只要有上述条件有一条不满足,就不会发生死锁

死锁的预防

我们可以通过破坏产生死锁的四个必要条件来预防死锁,由于资源互斥是固有特性无法改变的

破坏“请求与保持”条件

方法一:静态分配,每个进程在开始执行时就申请他所需要的全部资源

方法二:动态分配,每个进程在申请所需要的资源时他本身不占用系统资源

破坏“不可剥夺”条件

一个进程不可获得其所需要的全部资源便处于等待状态,等待期间他占用的资源将被隐式的释放重新加入到系统的资源列表中,可以被其他进程使用,而等待的进程只有重新获得自己原有的资源以及新申请的资源才可以重新启动,执行

破坏“循环等待”条件

采用资源有序分配的基本思想。将系统中的资源顺序进行编号,将紧缺的、稀少的资源采用较大的编号,申请资源时必须按照编号的顺序执行,一个进程只有较小编号的进程才能申请较大编号的进程

死锁的避免

基本思想:系统对进程发出每一个系统能够满足的资源申请进行动态检查,并根据检查结果决定是否分配资源,如果分配后系统可能发生死锁,则不予分配,否则分配。这是一种动态策略。典型的避免死锁的算法试银行家算法。

Last Updated:
Contributors: 156081289@qq.com