
上期回顾: 【操作系统】进程与线程
个人主页:GUIQU.
归属专栏:操作系统

正文
1. 进程同步
1.1 定义与重要性
进程同步是指对多个相关进程在执行次序上进行协调,使得它们能够按照一定的规则和顺序来访问共享资源或者协同完成某项任务。在多进程环境下,如果没有合适的同步机制,各个进程随意地访问共享资源,就很容易出现数据不一致、程序逻辑混乱等问题,所以进程同步对于保证系统的正确性和稳定性至关重要。
例如,在一个火车票售票系统中,多个售票窗口(可看作多个进程)同时售卖同车次的车票,车票剩余数量就是它们共享的资源。如果没有同步机制,可能会出现多个窗口同时卖出同一张车票的情况,导致数据出错。而通过合适的进程同步手段,就能确保每个车票的售卖操作都是有序且正确的,不会出现这种冲突问题。
1.2 常见的进程同步机制
-
临界区(Critical Section):
- 概念:临界区是一段代码,在这段代码中进程访问共享资源,而同一时刻只允许一个进程进入临界区访问该共享资源,其他想要访问的进程必须等待。例如在上述火车票售票系统中,修改车票剩余数量的代码部分就是临界区,每次只能有一个售票窗口对应的进程进入这里进行操作。
- 实现原则:为了保证临界区的正确使用,需要遵循以下原则:
- 空闲让进:当没有进程处于临界区时,应该允许一个请求进入临界区的进程立即进入。
- 忙则等待:如果已有进程在临界区内,其他试图进入临界区的进程必须等待。
- 有限等待:一个进程在提出进入临界区的请求后,应能在有限时间内进入临界区,避免出现进程一直等待却无法进入的“饥饿”现象。
- 让权等待:当进程不能进入临界区时,应立即释放 CPU 资源,避免占用 CPU 进行无效等待。
-
信号量(Semaphore):
- 基本原理:信号量是一个整型变量,它被用于控制多个进程对共享资源的访问,同时还可实现进程间的同步。它有两个标准的原子操作(不可被中断的操作),即
P操作(一般也叫wait操作)和Q操作(也叫signal操作或V操作)。P操作会使信号量的值减 1,如果减 1 后的值小于 0,则当前进程阻塞等待;Q操作会使信号量的值加 1,如果加 1 后的值小于等于 0,则唤醒一个正在等待的进程。 - 应用示例:还是以火车票售票系统为例,可以设置一个信号量
mutex初始值为 1,代表车票资源的互斥访问权限。每个售票窗口对应的进程在售卖车票(访问共享的车票剩余数量资源)前执行P(mutex)操作,若能成功(即mutex值减 1 后不小于 0)则进入临界区操作车票资源,操作完后执行Q(mutex)操作,释放权限,允许其他进程进入临界区。这样就通过信号量实现了对车票售卖这一共享资源访问的同步控制。
- 基本原理:信号量是一个整型变量,它被用于控制多个进程对共享资源的访问,同时还可实现进程间的同步。它有两个标准的原子操作(不可被中断的操作),即
-
管程(Monitor):
- 结构与功能:管程是一种高级的同步抽象机制,它将共享资源以及对这些资源进行操作的相关过程封装在一个模块内,这个模块内部定义了一组数据结构(用于表示共享资源)和操作这些数据结构的过程(类似函数),并且保证同一时刻只有一个进程能进入管程内访问共享资源。就好比把火车票售票系统中涉及车票管理的所有资源和操作都放在一个“黑盒子”(管程)里,外面的进程要通过规定的入口(管程内定义的操作过程)才能对车票资源进行操作,而且每次只能有一个进程进去操作。
- 特点与优势:管程提高了程序的模块化程度和可读性,相比于直接使用信号量等机制,它把资源管理和同步控制集中起来,更便于程序员理解和维护代码,减少了因为分散的同步代码而导致的错误概率。同时,管程内部可以自动处理进程等待和唤醒等复杂的同步问题,程序员只需按照管程规定的方式来编写操作共享资源的代码即可。
2. 进程通信(IPC,Inter-Process Communication)
2.1 通信目的
不同进程在操作系统中通常是相互独立运行的实体,但在很多情况下它们需要相互协作、交换信息,这就需要进程通信机制。例如,一个进程负责生成数据,另一个进程负责对这些数据进行分析处理,那么就需要一种方式让生成数据的进程把数据传递给负责分析处理的进程,这就是进程通信要解决的问题。
2.2 常见的进程通信方式
-
管道(Pipe):
- 无名管道(Anonymous Pipe):
- 特点与使用场景:无名管道是一种半双工的通信方式,即数据只能单向流动,它通常用于具有亲缘关系(比如父子进程)之间的通信。管道在内存中开辟一块缓冲区,一端用于写入数据(写端),另一端用于读取数据(读端)。例如在 Linux 系统中,父进程通过
fork()函数创建子进程后,可以创建一个无名管道,父进程向管道写端写入命令,子进程从管道读端读取命令并执行相应操作,实现父子进程间简单的单向命令传递与协作。 - 局限性:无名管道只能在有亲缘关系的进程间使用,而且通信是单向的,如果要实现双向通信,需要创建两个管道;同时,管道的缓冲区大小是有限的,如果写入的数据超过缓冲区容量,写入操作会被阻塞,直到有足够空间可以继续写入。
- 特点与使用场景:无名管道是一种半双工的通信方式,即数据只能单向流动,它通常用于具有亲缘关系(比如父子进程)之间的通信。管道在内存中开辟一块缓冲区,一端用于写入数据(写端),另一端用于读取数据(读端)。例如在 Linux 系统中,父进程通过
- 有名管道(Named Pipe):
- 特点与使用场景:有名管道克服了无名管道只能用于亲缘关系进程间通信的局限,它有一个文件名标识,不同的、无亲缘关系的进程可以通过这个文件名来访问同一个管道进行通信。比如在一个分布式系统中,不同主机上的两个进程(它们之间无亲缘关系),可以通过创建有名管道(在共享的文件系统中创建管道文件),然后按照约定的方式,一个进程向管道写入数据,另一个进程从管道读取数据,实现跨进程、跨主机(如果管道所在文件系统支持共享的话)的通信。
- 局限性:有名管道虽然解决了部分无名管道的局限,但它仍然是基于文件系统的半双工通信方式,通信效率相对不是特别高,并且在处理大量、实时性要求高的数据通信时可能不太适用。
- 无名管道(Anonymous Pipe):
-
消息队列(Message Queue):
- 工作原理:消息队列是一种基于消息的、先进先出(FIFO)的进程间通信方式。进程可以把要发送的消息封装成一定格式的数据结构(包含消息类型、消息内容等信息),然后将其发送到消息队列中,其他进程可以按照消息队列的顺序从队列中获取消息并进行处理。消息队列独立于发送和接收进程存在,它可以存储多个消息,并且不同进程可以通过相同的消息队列标识符来访问这个队列进行通信。
- 优势与应用场景:消息队列能够传输有格式的数据,不像管道只能传输无格式的字节流,方便了对不同类型消息的区分和处理;同时,它可以解决管道缓冲区大小受限的问题,消息可以在队列中积累,接收进程可以根据自己的节奏来获取和处理消息,适用于异步通信场景,比如在一个企业级的消息处理系统中,不同模块对应的进程(如订单生成进程、库存管理进程、物流调度进程等)可以通过消息队列来传递订单信息、库存变化信息、物流安排信息等,实现业务流程的协同工作。
-
共享内存(Shared Memory):
- 原理与特点:共享内存是一种将同一块物理内存区域映射到多个进程的地址空间中,使得多个进程可以直接对这块共享内存进行读写操作来实现信息交换的通信方式。它是所有进程间通信方式中速度最快的,因为不需要像其他方式那样进行多次数据拷贝等操作,多个进程直接访问共享内存就如同访问自己的内存一样。例如在一个多媒体处理系统中,一个进程负责采集视频数据并将其存入共享内存,另一个进程直接从共享内存中读取数据进行视频编码等后续处理,这样可以高效地实现数据传递。
- 挑战与解决措施:共享内存的主要挑战在于多个进程同时读写共享内存时容易出现数据不一致、相互干扰等同步和互斥问题。为了解决这个问题,通常需要配合使用信号量等同步机制,例如设置合适的信号量来控制只有一个进程能在某一时刻对共享内存的关键区域进行写入操作,其他进程如果要写入则需要等待,以此保证共享内存使用的正确性和稳定性。
-
信号(Signal):
- 作用与特点:信号是一种异步的进程间通信方式,用于通知一个进程某个事件的发生。比如当用户按下键盘上的
Ctrl + C组合键时,操作系统会向当前正在运行的进程发送一个中断信号(如SIGINT信号),进程接收到这个信号后,可以根据预先设置的信号处理程序来做出相应的反应(如正常终止程序、保存数据后终止等)。信号通常携带的信息量较少,只是起到一个通知作用,告知进程有特定事件发生了,它可以用来实现简单的进程间交互和控制。 - 应用场景:在系统管理、守护进程监控等场景中应用较多。例如,一个守护进程负责监控系统的某些资源状态,当发现资源不足(如内存使用率过高)时,可以向相关的管理进程发送一个特定的信号,通知其采取相应的措施(如释放内存、调整资源分配等),实现对系统的动态管理和维护。
- 作用与特点:信号是一种异步的进程间通信方式,用于通知一个进程某个事件的发生。比如当用户按下键盘上的
-
套接字(Socket):
- 基于网络的通信方式:套接字主要用于网络环境下不同主机上的进程之间的通信,当然也可以用于同一主机上不同进程间的通信。它基于网络协议(如 TCP/IP 协议等),通过创建套接字,进程可以在网络上建立双向的、可靠的通信连接,就像在网络两端的进程之间搭建了一条“通信管道”。例如在一个网络聊天应用中,客户端进程和服务器端进程通过套接字建立连接,然后可以互相发送和接收聊天消息,实现跨网络的实时通信。
- 广泛的应用领域:套接字在网络编程中应用极为广泛,涵盖了互联网应用、企业内部网络通信、分布式系统等众多领域,凡是涉及到网络交互的程序,基本都会用到套接字来实现进程间的通信与协作。
综上所述,进程同步与通信机制是操作系统中保障多进程协调工作、高效运行以及实现复杂系统功能的关键所在,不同的同步和通信方式各有其特点和适用场景,程序员需要根据具体的应用需求来合理选择和运用这些机制。
结语
感谢您的阅读!期待您的一键三连!欢迎指正!


7502

被折叠的 条评论
为什么被折叠?



