操作系统——2.进程与线程


JAVA后端开发知识总结(持续更新…)


进程、线程、协程


参考文档

B站:《王道考研 操作系统》
《现代操作系统》
《Linux的管道》

《进程间通信IPC》



零、进程、线程、协程

1、进程与线程的区别

在这里插入图片描述

  • 资源层面:进程是资源分配的基本单位;线程几乎不拥有系统资源,线程可以访问隶属进程的资源,并且同一进程的不同线程间共享进程资源()。
  • 系统调度层面: 线程是CPU分派、调度的基本单位,是进程内的一个执行单元,也是进程内的可调度实体,它是比进程更小的能独立运行的基本单位;而进程是除CPU外的系统资源分配的基本单位。
  • 系统开销层面:创建进程需要操作系统为其分配或回收资源(内存空间、I/O资源等),开销较大,且在进程切换时,需要保存进程PCB信息和恢复另一进程的执行环境;而线程的切换只会涉及少量寄存器和缓存内容,开销较小。
  • 通信层面:进程间通信需要依靠IPC(进程间通信)完成;而同一进程的不同线程由于共享地址空间,其通信主要通过共享内存,甚至不需要系统干预。
  • 地址空间层面::进程内至少有一个线程,它们共享进程的地址空间,而进程有自己独立的地址空间。

2、线程与协程的区别

  协程是一种协作式的用户态的轻量级线程,协程的调度和保护、恢复现场完全由用户控制。从技术的角度来说,“协程就是用户可以暂停执行的函数”。缺点也在于它需要在应用层实现的内容(调用栈、调度器)特别多。
  协程拥有自己的寄存器上下文和栈,协程调度切换时,将寄存器上下文和栈保存到其它地方,在切回来的时候,恢复先前保存的寄存器上下文和栈。直接操作同一个栈则基本没有内核切换的开销,无需系统自动切换(系统自动切换会浪费很多的资源),可以不加锁地访问全局变量,所以上下文的切换非常快。

  • 一个线程可以有多个协程,一个进程也可以单独拥有多个协程。
  • 线程进程都是同步机制,而协程则是异步
  • 协程能保留上一次调用时的状态,每次过程重入时,就相当于进入上一次调用的状态。
  • 线程是抢占式,而协程是非抢占式的,所以需要用户自己释放使用权来切换到其它协程,因此同一时间其实只有一个协程拥有运行权,相当于单线程的能力。
  • 要使用协程之前,必须要保证所有的操作都是非阻塞的。
  • 线程是被分割的CPU资源,协程是组织好的代码流程,协程需要线程来承载运行,但协程不会直接使用线程,而是直接利用Interceptor
  • 线程是协程的资源,协程通过Interceptor来间接使用线程这个资源。

一、进程

1、进程的定义与组成

1.1 进程实体与进程

  • 程序:是静态的,就是个存放在磁盘里的可执行文件,就是一系列的指令集合。
  • 进程(Process):是动态的,是程序的一次执行过程,同一个程序多次执行会对应多个进程。是资源分配的基本单位
  • 为了方便操作系统管理,完成各程序的并发执行,引入了进程、进程实体的概念:

  进程实体(进程映像,简称进程)由内存中的程序段、数据段和PCB(进程控制块)三部分组成(注意:PCB是进程存在的唯一标志)。   
  进程是进程实体的运行过程,是系统进行资源分配和调度的独立单位。
  严格来说进程实体和进程是不一样的,进程实体是静态的,而进程则是动态的。但广义上,可以认为进程实体就是进程。

1.2 进程的组成

  进程(进程实体)由内存中的程序段、数据段和PCB(进程控制块)三部分组成。内存中PCB中存储操作系统对进程管理的信息,是给操作系统使用的,而程序段和数据段是进程自己使用的。
在这里插入图片描述

1.2.1 PCB

  操作系统对各个并发运行的进程进行管理工作所需的信息都存在PCB中(但凡管理时所需要的信息,都会被放在PCB中)。

在这里插入图片描述

1.3 进程拥有的资源

  • 堆和栈
  • 存放程序正文、数据的磁盘和内存地址空间
  • 运行时所需要的I/O设备
  • 已打开的文件
  • 信号量

1.4 进程地址空间

这篇文章!!
在这里插入图片描述

2、进程的组织

  在一个系统中,通常有数十、数百乃至数千个PCB。为了能对它们加以有效的管理,应该用适当的方式把这些PCB组织起来
  进程的组成讨论的是一个进程内部由哪些部分构成的问题,而进程的组织讨论的是多个进程之间的组织方式问题。

链接方式

  • 通过按照进程状态将PCB分为多个队列,操作系统持有指向各个队列的指针。
    在这里插入图片描述

索引方式

  • 根据进程状态的不同建立若干索引表,操作系统持有指向各个索引表的指针。
    在这里插入图片描述

3、进程的五大特征

  1. 动态性:进程是程序的一次执行过程,是动态产生、变化和消亡的(基本特征)。
  2. 并发性:内存中由多个进程实体,各进程并发执行。
  3. 独立性:进程是能够独立运行、独立获取资源、独立接受调度的基本单元。
  4. 异步性:进程按照自己独立的、不可预知的速度向前推进,导致运行结果的不确定性,而操作系统需要提供 “进程同步机制” 来解决异步问题。
  5. 结构性:每个进程都配置有一个PCB,并且由程序段、数据段共同组成。

4、进程的状态与转换

4.1 进程的状态

操作系统为了方便对进程的管理,将进程分为三种基本状态

  • 运行态:占有CPU,并在CPU上运行(每个CPU核心同一时刻只有一个进程处于运行态)。
  • 就绪态:已经具备运行条件,但没有空闲CPU,暂时不能运行(等待获取CPU资源)。
  • 阻塞态:因为某一事件而暂时不能运行(如等待I/O操作的结果,为提高CPU利用率,进程需要将其它所需资源分配到位,才能得到CPU的服务)。

按照进程的生命周期来看,进程可分为另外两种状态:

  • 创建态:在进程被创建的时候,操作系统为进程分配资源,初始化PCB。
  • 终止态:在进程被从系统中撤销,操作系统会回收进程拥有的资源,并撤销PCB。

4.2 进程状态的转换

  • 运行态到阻塞态是进程本身的主动行为(申请某种系统资源)。
  • 阻塞态到就绪态是进程的被动行为(其它系统资源就绪,但还没分配到CPU)。
  • 运行态 -> 阻塞态 -> 就绪态是一个进程从资源申请开始的单向变化

在这里插入图片描述

5、进程控制——进程状态转换

5.1 进程控制的实现

  进程控制由原语实现,它的主要功能是对系统中的所有进程实施有效的管理,它具有创建新进程、撤销已有进程、实现进程状态转换等功能。总而言之,进程控制就是要实现进程状态的转换

在这里插入图片描述

5.2 原语

  进程状态变化时,往往需要同时改变PCB内容和其所所处的队列,这必须是一个原子性的操作。因此,需要原语来实现进程控制。

  原语是原子操作,采用“关中断指令”和“开中断指令”来保证原子性。在关中断后、开中断前的指令执行期间,进程将不会响应中断,所以开/关中断指令权限很大,是必须在核心态下执行的特权指令

  原语通常分为创建、撤销、阻塞、唤醒、切换五种,其中,阻塞原语和唤醒原语需要成对出现。无论哪类原语,都要做以下三类事情:

  • 更新PCB中的信息
    • a. 所有的进程控制原语一定都会修改进程状态标志
    • b. 剥夺当前运行进程的CPU使用权必然需要保存其运行环境
    • c. 某进程开始运行前必然要恢复其运行环境
  • 将PCB插入合适的队列
  • 分配/回收资源

6、进程通信

  进程通信就是指进程之间的信息交换。进程是分配系统资源的单位(包括内存地址空间),因此各进程拥有的内存地址空间相互独立。为了保证安全,一个进程不能直接访问另一个进程的地址空间,所以进程之间要交换数据必须通过内核,在内核中开辟一块缓冲区,进程1把数据从用户空间拷到内核缓冲区,进程2再从内核缓冲区把数据读走,内核提供的这种机制称为进程间通信(IPC)。进程间的通信可分为共享内存、消息传递和管道通信

  由于每个进程的用户空间都是独立的,不能相互访问,这时就需要借助内核空间来实现进程间通信,原因很简单,每个进程都是共享一个内核空间。

  • 四次拷贝

1、由用户空间的buf中将数据拷贝到内核中。
2、内核将数据拷贝到内存中。
3、内存到内核。
4、内核到用户空间的buf。

  • 两次拷贝

1、用户空间到内存。
2、内存到用户空间。

6.1 管道/匿名管道(pipe)通信

  • 管道通信:指用于连接读写进程的一个共享文件,又名pipe 文件,是在内存中开辟的一个大小固定的缓冲区。它单独构成一种独立的文件系统。
  • 管道的实质是一个内核缓冲区,是用环形队列实现的,进程以先进先出的方式从缓冲区存取数据。
  • 由两个打开的文件描述符引用,一个指向读端,一个指向写端。因此要通信的两个进程必须从它们的公共祖先那里继承管道文件描述符。
  • 只能用于父子进程或兄弟进程等具有亲缘关系(公共祖先) 的进程之间。
  • 四次拷贝。

在这里插入图片描述

  1. 管道只能采用半双工通信,某一时间段内只能实现单向的传输。如果要实现双向同时通信,则需要设置两个管道。
  2. 各进程要互斥地访问管道。
  3. 数据以无格式字节流的形式写入管道,当管道写满时,写进程的write()系统调用将被阻塞,等待读进程将数据取走。当读进程将数据全部取走后,管道变空,此时读进程的read()系统调用将被阻塞
  4. 数据一旦被读出,就从管道中被抛弃,这就意味着读进程最多只能有一个,否则可能会有读错数据的情况。

6.2 有名管道(FIFO)

  • 有名管道提供了一个路径名与管道关联,以真正且独立的磁盘文件形式存在于实际文件系统中,可以通过访问文件路径实现本机任意两个进程通信。
  • 有名管道不支持诸如lseek()等文件定位操作,因此严格遵循先进先出。为了保证同步,同样是一个只能单方向访问的文件。

6.3 共享内存

  • 共享内存:设置一个共享空间,各进程互斥访问共享空间,直接读写内存避免了管道和消息队列通信方式从内核到用户空间的四次拷贝,效率最高
  • 两次拷贝。
  • 内核专门留出了一块内存,访问的进程可以将其映射到自己的私有地址空间,进程就可以直接读写这一块内存而不需要进行系统调用。
  • 共享内存可以解决消息队列通信中用户态与内核态之间数据拷贝过程带来的开销,它直接分配一个共享空间,每个进程都可以直接访问,但是多进程竞争同个共享资源会造成数据的错乱。
  • 需要同步机制(如信号量)来达到进程间的同步及互斥访问。
  • 共享内存可以随机访问被映射文件的任意位置。

在这里插入图片描述

6.4 消息队列

  • 消息队列:存放在内核中的消息链表,每个消息队列由消息队列标识符表示。一般只有在内核重启(OS重启才被删除)。
  • 将消息格式化(消息头/消息体),并使用系统sendreceive原语控制,克服缓冲区大小限制、传递信息少的问题。
  • 在某个进程往一个队列写入消息之前,并不需要另外某个进程在该队列上等待消息的到达。
  • 允许一个或多个进程进行读写。
  • 消息队列通信的速度不是最及时的,因为每次数据的写入和读取都需要经过用户态与内核态之间的拷贝过程。

在这里插入图片描述

6.5 信号量

  • 信号量:本质为一个计数器,控制多个进程对共享资源的同步访问(实际是个锁机制),主要作为进程间或同一进程内不同线程的同步手段。
  • 信号量通常是在内核中实现的,需要保证P、V操作的原子性。

6.6 套接字

  • 主要用于不同机器间进程的网络通信。具体可见这篇文章
  • 套接字是支持TCP/IP的网络通信的基本操作单元,可以看做是不同主机之间的进程进行双向通信的端点。

6.7 信号

  • 信号Signal:是一种比较复杂的通信方式,用于通知接收进程某个事件已经发生。
  • 信号可以在任何时候发给某一进程,而无需知道该进程的状态。
  • 信号可以在用户空间进程和内核之间直接交互,内核可以利用信号来通知用户空间的进程发生了哪些系统事件。

7、线程共享进程的内容和独占内容

  • 进程代码段
  • 进程的共有(全局)数据:利用这些共享的数据,线程很容易实现相互之间的通讯
  • 进程打开的文件描述符
  • 信号处理器
  • 进程的当前目录
  • 进程的用户ID与进程组ID
  • 线程 ID:唯一
  • 寄存器组的值(程序计数器):每个线程有自己不同的运行线索,当从一个线程切换到另一个线程上时,必须将原有的线程的寄存器集合的状态保存,以便将来该线程在被重新切换到时能得以恢复
  • 线程的栈
  • 错误返回码
  • 线程的信号屏蔽码:但是共享信号处理器

8、进程间同步

  • 信号量
  • 互斥量
  • 管程
  • 进程间通信

二、线程

1、线程

1.1 线程的概念与属性

  进程是程序的一次执行,但是有的进程可能需要“同时”执行很多事(比如QQ的聊天、音乐等),这些功能显然需要用不同的几段程序才能实现,并且几段程序还要并发运行。
  为此,引入了线程,来增加并发度

  线程是为了满足一个进程“同时”执行多个任务而被分解成的并发的多个顺序线程,为的是增加并发度。它是进程内的一个执行单元,也是进程内的可调度实体。
  在引入线程概念后,线程成为CPU执行单元(调度)的基本单元,进程成为除CPU外的系统资源分配的基本单元。进程依然是资源分配的基本单位,从属于同一进程的各个线程共享进程的资源。

线程的属性

在这里插入图片描述

1.2 线程的实现方式

  • 用户线程:由应用程序通过线程库实现,所有的线程管理工作都由应用程序负责(包括线程切换)。用户级线程中,线程切换可以在用户态下完成,无需操作系统干预(对用户不透明,对操作系统透明)。

  • 内核线程:管理工作由操作系统内核完成,线程调度、切换等工作都由内核负责,因此内核级线程的切换必然需要在核心态下才能完成。因此,只有内核级线程才是处理机分配的单位

实例解析

在这里插入图片描述

1.3 线程间的同步方式

  线程同步是两个或多个共享资源的线程的并发执行,应该同步线程以避免共享资源使用冲突。

  • 互斥量(Mutex):只有拥有互斥对象的线程才有访问公共资源的权限。比如 Java 中的 synchronized 关键词和各种 Lock 都是这种机制。
  • 信号量:它允许同一时刻多个线程访问同一资源,但是需要控制同一时刻访问此资源的最大线程数量。
  • 事件(Event):Wait/Notify,通过通知操作的方式来保持多线程同步,还可以方便地实现多线程优先级。
  • 临界区

2、多线程

2.1 多线程模型

  在同时支持用户级线程和内核级线程的系统中,由几个用户级线程映射到几个内核级线程的问题引出了“多线程模型”问题。

  • 多对一模型(一个内核级线程对应多个用户级线程): 优点在于用户线程切换都是在用户态下完成,进程管理开销小效率高。 缺点在于一个用户线程阻塞,其它的用户线程都被阻塞,并发度低。
  • 一对一模型(一个内核级线程对应一个用户级线程): 优点在于各个用户线程分配到多核处理器并行执行,并发度高。 缺点在于用户线程切换要基于内核线程的切换,需要在核心态下完成,进程管理开销大。
  • 多对多模型:集二者所长。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值