跳转至

Chapter3:Process Concept

章节概述(Part Two: Process Management)

  • Part Two 总体结构(Page 2)
  • 进程管理部分,包括进程概念、调度、多线程、同步和死锁。
  • 本章焦点:进程作为执行中的程序,是所有计算的基础。
  • 章节目标(Page 4)
  • 介绍进程:定义、组成、状态转换。
  • 描述进程管理:调度(CPU 分配)、创建/终止、通信。
  • 探索进程间通信(IPC):共享内存和消息传递。
  • 描述客户端-服务器系统中的通信。

3.1 Process Concept

3.1.1 进程概念总览

进程概念的核心是支撑多道程序设计与分时系统的并发执行,具体特征如下: - 并发执行场景:在多道程序系统(批处理系统,以“作业”为单位)和分时系统(以“任务”为单位)中,多个程序(包括用户程序与操作系统程序)会同时并发执行,而非单一程序独占资源。 - 程序的多实例执行:同一个程序可被多次加载执行,每次执行时处理不同的数据(例如多个用户同时运行“记事本”程序)。 - 程序执行与进程状态的关联:程序执行会经历“启动→执行→暂停→结束”等阶段,这些动态阶段对应进程的不同状态,进程正是用于描述程序并发执行过程的核心载体。

3.1.2 进程定义

  • 本质属性:进程是“执行中的程序”,是操作系统进行资源分配与调度的基本单位;与程序(静态存储在磁盘的可执行文件,被动实体)不同,进程是动态活动的实体。
  • 执行特性:进程的执行必须遵循顺序逻辑,即按指令序列逐步推进,其动态性通过“进程状态”的变化体现。
  • 资源依赖:操作系统会为进程分配完成任务所需的资源,包括CPU、内存、I/O设备等。
  • 术语关联:文档中“作业(job)”与“进程(process)”两个术语几乎可互换使用,前者更侧重批处理系统中的任务单位,后者是通用的动态执行单位。

3.1.3 进程组成

进程由“进程控制块(PCB)”与特定的内存布局共同构成,两者分别负责进程的管理与数据/代码存储:

3.1.3.1 进程控制块(Process Control Block, PCB)

PCB是操作系统内核中用于管理进程的数据结构(又称“任务控制块”),是进程的“身份标识”,包含以下关键信息: - 进程状态:标识进程当前所处的状态(如运行、就绪、等待); - 程序计数器:记录进程下一条待执行指令的内存地址; - CPU寄存器:存储进程执行时CPU各寄存器的当前值(如通用寄存器、状态寄存器); - CPU调度信息:包括进程优先级、调度队列指针等,用于CPU调度决策; - 内存管理信息:记录进程占用的内存空间(如地址范围、内存块分配情况); - 记账信息:统计进程使用的系统资源(如CPU占用时间、已运行时长、资源限制); - I/O状态信息:记录进程已分配的I/O设备(如磁盘、打印机)、已打开的文件列表等。

3.1.3.2 进程的内存布局

进程在内存中按功能划分为四个核心区域,各区域职责明确: - 文本段(Text Section):存储程序的可执行代码(即程序指令),是只读区域,确保代码不被意外修改; - 数据段(Data Section):存储进程的全局变量与静态变量,在进程加载时被初始化; - 堆(Heap):用于进程运行时动态分配内存(如通过mallocnew等函数申请的内存),内存大小可动态调整,由程序员手动管理或由垃圾回收机制回收; - 栈(Stack):存储临时数据,包括函数参数、返回地址、局部变量等,遵循“先进后出”原则,由CPU自动分配与释放(函数调用时入栈,函数返回时出栈)。

3.1.4 进程状态

进程是动态实体,其生命周期内会在不同状态间转换,核心状态与转换逻辑如下:

3.1.4.1 核心状态定义

  • 新建态(New):进程正在被创建,操作系统正在为其分配资源、创建PCB,尚未进入就绪队列;
  • 就绪态(Ready):进程已具备运行条件(资源已分配),但等待CPU空闲以获得执行权,位于“就绪队列”中;
  • 运行态(Running):进程正在CPU上执行指令,独占CPU资源(单CPU系统中同一时间仅一个进程处于此状态);
  • 等待态(Waiting):进程因等待某事件(如I/O完成、资源释放)而暂时无法执行,主动放弃CPU,进入“设备队列”或“等待队列”;
  • 终止态(Terminated):进程完成所有执行任务,或因错误/被强制终止而退出,操作系统会回收其占用的资源。

3.1.4.2 状态转换流程

核心转换路径为:
新建态 → 就绪态(OS完成进程创建,加入就绪队列)→
就绪态 → 运行态(CPU调度器选中进程,分配CPU)→
运行态 → 等待态(进程请求I/O或等待资源,主动放弃CPU)/ 运行态 → 终止态(进程执行完成或被终止)→
等待态 → 就绪态(等待事件完成,进程重新具备运行条件,回到就绪队列)。

补充:实际操作系统(如Linux)的进程状态更细分(如可中断睡眠态、不可中断睡眠态、僵尸态、暂停态),但核心逻辑基于上述五大状态扩展。

3.1.5 上下文切换(Context Switch)

  • 定义:当CPU从一个进程切换到另一个进程执行时,操作系统需保存“旧进程”的状态(即PCB中记录的CPU寄存器、程序计数器、进程状态等信息),并加载“新进程”之前保存的状态,这一过程称为上下文切换。
  • 触发场景:常见于“运行态→就绪态”(如时间片到期)、“运行态→等待态”(如进程请求I/O)等情况,此时CPU需释放当前进程,切换到新进程执行。
  • 关键依赖:上下文切换的核心是“保存与恢复PCB”,PCB中记录的进程上下文(状态、寄存器、地址空间等)是切换的唯一依据;切换耗时属于系统开销,PCB越复杂、操作系统功能越丰富,上下文切换时间越长。

3.1.6 示例:程序执行与进程监控

文档通过“程序执行服务”与Windows任务管理器展示了进程的实际存在与状态: - 程序执行服务:当用户通过GUI点击、命令行输入等方式启动程序时,可执行文件被加载到内存,成为进程并开始执行,多个程序启动对应多个进程并发。 - Windows任务管理器示例:任务管理器的“进程”标签页会显示系统中所有进程的关键信息,包括: - 进程标识(PID,如OSPPSVC.EXE的PID为5928); - 资源占用(CPU使用率、内存使用量、I/O读写字节数); - 所属用户(如NETWORKyewenbupt); - 线程数、CPU累计占用时间等,直观体现了进程的动态运行状态与资源消耗情况。


3.2 Process Scheduling

3.2.1 调度概念

进程调度的核心是通过合理分配CPU及系统资源,平衡系统性能与用户体验,具体目标与运行基础如下: - 核心目标:包括最大化CPU利用率(避免CPU空闲)、提升系统吞吐量(单位时间完成的进程数)、最小化用户响应时间(从请求到反馈的延迟)、缩短进程周转时间(从创建到终止的总时间)及减少进程等待时间(在就绪/设备队列中的停留时间),这些目标共同保障系统高效运行。 - 多道程序设计支撑:调度机制基于多道程序设计原理,通过在内存中保持多个进程,由调度器动态选择其中一个进程分配CPU执行,避免单一进程等待I/O时导致CPU闲置,充分利用硬件资源。

3.2.2 调度队列(Scheduling Queues)

调度队列是进程调度的核心数据结构,用于管理不同状态的进程,实现进程在系统中的有序流转: - 核心队列类型: 1. 就绪队列(Ready Queue):存储所有已分配必要资源(如内存)、等待CPU执行的进程,通常以链表形式组织,进程进入此队列后等待短期调度器选择; 2. 设备队列(Device Queues):每个I/O设备对应一个设备队列,存储等待使用该设备的进程(如等待磁盘读写的进程),进程因请求I/O从运行态转入对应设备队列,I/O完成后回到就绪队列; 3. 作业队列(Job Queue):系统中所有进程的集合,包括未进入内存的后备进程与已在内存的进程,是长期调度器的调度对象。 - 队列结构与进程迁移:队列可采用链表、先进先出(FIFO)、优先级队列等结构;进程会在不同队列间迁移,例如“作业队列→就绪队列”(长期调度)、“就绪队列→CPU”(短期调度)、“CPU→设备队列”(请求I/O)、“设备队列→就绪队列”(I/O完成),形成完整的调度流转链路。

3.2.3 调度器类型

根据调度对象、频率与功能差异,进程调度器分为长期、短期、中期三类,各司其职以保障系统资源优化分配: - 长期调度器(Long-Term Scheduler / Job Scheduler): - 核心功能:从作业队列中选择合适的进程调入内存,为其分配内存等资源并创建PCB,使其进入就绪队列;通过选择进程的类型(I/O-bound或CPU-bound),控制“多道程序设计度”(内存中进程的数量); - 调用频率:较低(秒、分钟级),因此调度算法可相对复杂,无需追求极致速度; - 进程类型适配:倾向于选择I/O-bound进程(多为短CPU burst)与CPU-bound进程(少为长CPU burst)的合理组合,避免内存中全为某一类进程导致资源浪费(如全为I/O-bound会使CPU空闲,全为CPU-bound会使I/O设备空闲)。

  • 短期调度器(Short-Term Scheduler / CPU Scheduler)
  • 核心功能:从就绪队列中选择下一个将获得CPU的进程,将CPU分配给其执行;是多数系统中唯一的调度器,直接决定CPU的使用效率;
  • 调用频率:极高(毫秒级),因此调度算法需简洁高效,避免调度开销占用过多CPU时间。

  • 中期调度器(Medium-Term Scheduler)

  • 核心功能:通过“交换(Swapping)”机制,将内存中暂时不急需执行的进程(如等待时间较长的就绪进程、资源紧张时的部分进程)调出到外存交换区,释放内存资源;待系统资源充足或进程需执行时,再将其从外存调回内存进入就绪队列;
  • 作用:动态调整多道程序设计度,防止内存资源过度占用,保障内存中进程的执行效率,是内存管理与进程调度的衔接环节。

3.2.4 上下文切换开销

上下文切换是进程调度过程中不可避免的系统开销,其耗时与硬件支持、操作系统复杂度密切相关: - 开销产生原因:当CPU从一个进程切换到另一个进程时,需完成“保存旧进程状态→加载新进程状态”的操作——保存旧进程的CPU寄存器值、程序计数器、进程状态等(存储于PCB),再从新进程的PCB中加载这些信息到CPU寄存器与内存,同时可能需要刷新Translation Lookaside Buffer(TLB,地址转换缓存),这些操作均会消耗CPU时间; - 影响因素:开销大小取决于PCB的复杂度(PCB信息越多,保存/加载耗时越长)与硬件支持(部分硬件提供多组寄存器,可同时加载多个进程的上下文,减少切换时间);上下文切换本身不产生有用的计算工作,属于系统额外开销,因此操作系统需优化调度策略以减少不必要的切换。


3.3 Operations on Processes

3.3.1 进程创建(Process Creation)

进程创建是操作系统通过特定机制实现进程生命周期启动的核心操作,遵循树形结构与明确的资源、执行规则: - 创建关系与结构:进程创建以“父进程创建子进程”为核心模式,子进程可进一步创建孙进程,形成层级分明的进程树;例如Linux系统中,init进程(pid=1)是所有进程的根进程,所有其他进程均为其后代,构成完整的进程树结构🔶2-359、🔶2-370、。 - 核心系统调用:不同操作系统提供专用系统调用来触发进程创建——Unix/Linux系统中使用fork()系统调用,创建一个与父进程内存空间相同的子进程;Windows系统中使用CreateProcess()函数,通过指定可执行文件路径、进程信息结构体等参数创建子进程,文档中还提供了两种系统调用的代码示例(如fork()的C程序、CreateProcess()的Windows API程序)🔶2-393、🔶2-400、。 - 资源共享规则:父进程与子进程的资源共享存在三种可选模式:一是子进程共享父进程的所有资源(如内存空间、打开文件);二是子进程仅共享父进程资源的子集(如部分文件句柄);三是父进程与子进程不共享任何资源,子进程拥有独立的资源空间🔶2-361、🔶2-362、🔶2-363、。 - 执行方式:父进程与子进程的执行关系分为两类——一是两者并发执行,父进程无需等待子进程完成即可继续自身任务;二是子进程通过exec()系统调用(Unix/Linux)替换自身内存空间中的程序,加载新的可执行文件并执行,此时子进程的执行逻辑与父进程完全分离🔶2-365、🔶2-366、🔶2-367、。

3.3.2 进程终止(Process Termination)

进程终止标志着进程生命周期的结束,涵盖多种触发场景与特殊进程状态,具体规则如下: - 终止触发场景:进程终止可分为四类情况——正常退出(进程执行完最后一条语句,通过exit()系统调用主动请求终止)、错误退出(进程因逻辑错误无法继续,如参数非法)、致命错误(进程因系统级错误终止,如非法内存访问)、被其他进程杀死(父进程通过abort()或操作系统通过TerminateProcess()(Windows)强制终止子进程)🔶2-407、🔶2-408、。 - 核心系统调用:正常终止依赖exit()系统调用,进程通过该调用向操作系统返回状态数据(父进程可通过wait()调用获取),并释放自身占用的资源;强制终止则依赖abort()(父进程终止子进程)或TerminateProcess()(Windows系统专用),直接终止目标进程的执行🔶2-408、🔶2-409、🔶2-410、。 - 级联终止机制:部分操作系统规定,若父进程在未等待子进程终止的情况下先行终止,操作系统会触发“级联终止”——强制终止该父进程的所有子进程、孙进程等后代进程,确保无“无主”进程残留,该终止操作由操作系统主动发起🔶2-420、🔶2-421、。 - 特殊进程状态:进程终止后可能出现两种特殊状态——一是僵尸进程(Zombie):子进程通过exit()终止并释放资源,但父进程未调用wait()获取其终止状态,导致子进程的PCB(进程控制块)仍保留在系统中,处于僵尸态;二是孤儿进程(Orphan):父进程在未调用wait()的情况下终止,子进程失去父进程,此时系统会将其“收养”给init进程(Linux),由init进程负责后续的wait()操作与资源回收🔶2-425、🔶2-426、🔶2-427、🔶2-428、。

3.3.3 进程层次结构

不同操作系统的进程层次结构设计存在差异,主要分为“严格树形”与“无严格层次”两类: - Unix/Linux系统:严格树形结构:以init进程(pid=1)为根节点,所有进程均通过“父→子”的创建关系形成树形结构;例如init创建sshdlogin等进程,sshd再创建bash进程,bash又可创建emacsps等进程,每个进程都有明确的父进程,通过进程ID(pid)与父进程ID(ppid)维护层级关系🔶2-370、。 - Windows系统:无严格层次:Windows系统不强制进程形成树形结构,所有进程在逻辑上地位平等,即使进程A创建了进程B,进程B也无需依赖进程A存在,且系统不要求进程间维护严格的父子层级关联;这种设计使得Windows进程的独立性更强,无需遵循固定的层级约束🔶2-374、。


3.4 Interprocess Communication

3.4.1 IPC 动机

进程间通信(IPC)的核心是支撑“协作进程”的交互需求,区别于“独立进程”(无法相互影响),协作进程可通过IPC实现资源共享与行为协同,其动机主要包括以下四类: - 信息共享:多个进程需共同访问或交换数据(如多进程协作处理同一文件),通过IPC实现数据的安全传递与共享; - 计算加速:将复杂任务拆解为多个子任务,由不同进程并行执行(如分布式计算),通过IPC协调子任务进度与结果汇总,提升整体计算效率; - 模块化:按功能将系统拆分为独立进程(如浏览器的“浏览器进程”“渲染进程”“插件进程”),进程间通过IPC实现功能衔接,降低系统耦合度; - 便利性:用户操作需触发多个进程联动(如打开软件时,主进程启动辅助进程加载资源),IPC为进程间的联动提供便捷的通信机制🔶2-444、🔶2-445、🔶2-446、🔶2-447。

3.4.2 IPC 模型

操作系统提供两种核心IPC模型,分别基于“内存共享”与“消息中转”实现进程间交互,两者在通信效率、同步复杂度上存在显著差异:

3.4.2.1 共享内存(Shared Memory)

  • 核心定义:由操作系统分配一块内存区域,允许需通信的进程共同访问该区域,进程通过直接读写这块内存实现数据交换;通信过程由用户进程自主控制,而非依赖操作系统中转🔶2-499、🔶2-500、🔶2-501。
  • 关键特性
  • 优点:通信效率高——无需操作系统在进程间拷贝数据,进程直接操作内存,减少系统开销;
  • 缺点:需解决并发同步问题——多个进程可能同时读写共享内存,易导致数据不一致,需用户进程自行实现同步机制(如锁、信号量),文档中提及同步问题将在后续章节详细讨论🔶2-502、。
  • 实现逻辑:进程需先通过系统调用申请共享内存区域,再将该区域映射到自身地址空间,之后即可像操作私有内存一样读写共享区域,通信完成后释放共享内存。

3.4.2.2 消息传递(Message Passing)

  • 核心定义:进程间通过操作系统提供的“消息队列”传递数据,进程无需共享内存,仅需调用send()(发送消息)和receive()(接收消息)操作,由操作系统负责消息的转发与缓冲🔶2-506、🔶2-507、🔶2-509。
  • 核心操作与函数
  • 基础操作:send(message)(向目标进程/邮箱发送消息)、receive(message)(从目标进程/邮箱接收消息);
  • 系统函数:如msgget(key_t key, int msgflg)(创建或获取消息队列)、msgsend(int msgid, const void *msg_ptr, size_t msg_sz, int msgflg)(向消息队列发送消息)、msgrcv(int msgid, void *msg_ptr, size_t msg_st, long int msgtype, int msgflg)(从消息队列接收消息)🔶2-511、🔶2-574、。
  • 通信方式分类
  • 直接通信:进程需显式指定通信对象,如send(Q, message)(向进程Q发送消息)、receive(P, message)(从进程P接收消息);链路自动建立,每个通信对对应唯一链路,通常为双向链路🔶2-542、🔶2-543、🔶2-544;
  • 间接通信:通过“邮箱(Mailbox,又称端口)”中转消息,每个邮箱有唯一ID,进程需共享同一邮箱才能通信;链路仅在进程共享邮箱时建立,一个邮箱可关联多个进程,一对进程可共享多个邮箱🔶2-554、🔶2-555、🔶2-556。
  • 同步方式分类
  • 阻塞(同步)阻塞send——发送者需等待消息被接收后才继续执行;阻塞receive——接收者需等待消息到达后才继续执行;
  • 非阻塞(异步)非阻塞send——发送者发送消息后立即继续执行,无需等待;非阻塞receive——接收者若未获取到消息,会收到“空消息”并继续执行🔶2-592、🔶2-593、🔶2-594、🔶2-597、🔶2-598、🔶2-599、。
  • 缓冲机制:分为无缓冲(消息直接传递,无暂存)、有限缓冲(消息队列容量固定,满则阻塞发送者)、无限缓冲(消息队列容量无上限,发送者无需等待),由操作系统提供自动或显式缓冲支持🔶2-539、。

3.4.3 同步问题

IPC中的同步问题是保障协作进程数据一致性的关键,文档以“生产者-消费者问题”为典型范例,阐述同步需求与约束: - 问题定义:生产者进程生成数据并写入“环形共享缓冲区”,消费者进程从缓冲区读取数据并处理,需通过同步机制避免数据竞争与逻辑错误🔶2-471、🔶2-488、🔶2-489。 - 核心约束条件: 1. 生产者仅能向“空缓冲区”写入数据,若缓冲区满则阻塞; 2. 消费者仅能从“满缓冲区”读取数据,若缓冲区空则阻塞; 3. 多个生产者不能同时向同一空缓冲区写入数据; 4. 多个消费者不能同时从同一满缓冲区读取数据; 5. 生产者与消费者不能同时对同一缓冲区进行读写操作🔶2-490、🔶2-491、🔶2-492、🔶2-493、🔶2-494、🔶2-495。 - 实际意义:该问题是IPC同步的基础模型,多数实际场景(如基于邮箱的通信、共享内存的交互)均可抽象为生产者-消费者问题,其同步解决方案(如信号量、管程)可直接复用。


3.5 Examples of IPC Systems

3.5.1 POSIX 共享内存

POSIX 共享内存是基于共享内存模型的经典 IPC 实现,核心通过专用系统调用完成内存共享与映射,具体机制如下: - 核心操作函数:通过shm_open()系统调用创建或打开一个共享内存对象(类似文件操作),再通过mmap()函数将该共享内存对象映射到调用进程的地址空间,使进程可直接读写共享内存;通信完成后,需通过munmap()解除映射、shm_unlink()删除共享内存对象。 - 核心特点:遵循 POSIX 标准,可在兼容 POSIX 的操作系统(如 Unix、Linux)中跨进程使用,通信效率高,无需操作系统中转数据,但需进程自行处理同步问题(如通过信号量避免数据竞争)🔶2-499、🔶2-500、🔶2-501。

3.5.2 Mach 消息传递

Mach 操作系统的 IPC 基于消息传递模型,依托微内核架构,以“端口”为核心通信载体,具体设计如下: - 架构基础:Mach 为微内核设计,内核仅提供进程间通信、内存管理等核心功能,其他服务(如文件系统、网络)以用户态进程形式存在,需通过消息传递协作。 - 通信载体与操作:以“端口(Port)”为消息收发端点,每个端口对应唯一的通信对象(如进程、服务);进程通过send()向目标端口发送消息,通过receive()从自身端口接收消息,消息格式统一,包含目标端口标识、数据内容等;端口具备权限控制,仅授权进程可读写,保障通信安全🔶2-530、🔶2-554、🔶2-556。 - 核心特点:消息传递是 Mach 系统的核心机制,支持进程间、进程与内核间的高效通信,微内核架构下的服务协作完全依赖该 IPC 方式。

3.5.3 Windows 本地过程调用(Local Procedure Call, LPC)

Windows 的 LPC 是专为本地客户端-服务器架构设计的 IPC 机制,聚焦同一主机内进程的高效通信,具体特性如下: - 通信模型:基于客户端-服务器模式,客户端进程通过 LPC 调用服务器进程提供的“本地过程”(类似函数调用),本质是通过消息传递实现“过程调用”的抽象。 - 核心组件:以“端口对象(Port Object)”为通信中介,服务器进程创建端口并监听,客户端进程通过连接该端口与服务器建立通信链路;客户端发送的“过程调用请求”被封装为消息,通过端口传递给服务器,服务器执行过程后将结果封装为消息,再通过端口返回给客户端。 - 核心特点:仅支持同一主机内的进程通信,不支持网络通信;通信效率高,Windows 系统内的许多服务(如系统服务、应用组件)均通过 LPC 实现内部协作🔶2-604、🔶2-605、🔶2-638。

3.5.4 管道(Pipes)

管道是早期 IPC 机制,分为普通管道与命名管道,均基于“字节流”传输数据,适用于不同场景的进程通信:

3.5.4.1 普通管道(Ordinary Pipes)

  • 核心特性:通信方向为单向(半双工),仅支持有父子关系的进程(如父进程创建子进程后通过管道通信);管道无名称,仅能通过进程的文件描述符访问,无法被无关进程打开。
  • 操作逻辑:父进程通过pipe()系统调用创建管道(获得两个文件描述符:读端fd[0]、写端fd[1]),再通过fork()创建子进程,子进程继承管道的文件描述符;父进程关闭读端、子进程关闭写端(或反之),即可实现单向数据传输(如父进程写、子进程读)🔶2-670、🔶2-677、🔶2-681。
  • 系统适配:Windows 中称为“匿名管道(Anonymous Pipes)”,核心逻辑与 Unix 普通管道一致,仅支持父子进程通信。

3.5.4.2 命名管道(Named Pipes)

  • 核心特性:通信方向为双向(全双工),支持任意进程(无需父子关系)通信;管道有唯一名称(如 Unix 中的“路径名”、Windows 中的“\.\pipe\管道名”),进程通过名称打开管道即可建立通信。
  • 操作逻辑:一个进程作为“服务器”创建命名管道并监听连接,其他进程作为“客户端”通过管道名称连接服务器;连接建立后,双方可同时读写管道,实现双向数据传输。
  • 核心特点:兼容性强,Unix 与 Windows 系统均支持;可跨进程(甚至跨用户)通信,但仅支持同一主机内的进程,不支持网络通信🔶2-670、🔶2-692、🔶2-693。

3.5.5 套接字(Sockets)

套接字是支持网络通信的 IPC 机制,本质是“网络通信端点”,可实现同一主机或不同主机间进程的通信,具体设计如下: - 核心定义:套接字由“IP 地址 + 端口号”唯一标识,IP 地址定位主机,端口号定位主机内的目标进程(如端口 80 对应 HTTP 服务);通信需建立在一对套接字之间(客户端套接字与服务器套接字)。 - 通信类型: - 面向连接(TCP):通信前需建立 TCP 连接,数据传输可靠、有序,适用于对可靠性要求高的场景(如文件传输); - 无连接(UDP):通信前无需建立连接,数据传输不可靠、无序,但效率高,适用于实时性要求高的场景(如视频流); - 多播套接字(MulticastSocket):支持向多个目标进程同时发送数据,适用于组播场景。 - 核心特点:不仅支持同一主机内的进程通信,还支持跨网络(如互联网)的进程通信,是客户端-服务器架构(如 Web 服务、远程登录)的核心 IPC 方式;端口号中 0-1023 为“知名端口”,用于标准服务(如端口 80 对应 HTTP)🔶2-605、🔶2-611、🔶2-612。


3.6 Communication in Client-Server Systems

3.6.1 套接字(Sockets)

套接字是客户端-服务器系统中跨网络通信的核心端点,通过标准化的地址标识与通信类型,实现进程间的网络交互,具体特性如下: - 地址组成:套接字由“IP地址 + 端口号”唯一标识,IP地址用于定位网络中的目标主机,端口号用于区分主机内提供不同服务的进程(如端口80对应HTTP服务);特殊IP地址127.0.0.1(回环地址)用于定位进程所在的本地系统,所有端口号中0-1023为“知名端口”,专用于标准系统服务🔶2-612、🔶2-613、🔶2-616、🔶2-617。 - 通信类型: 1. 流套接字(基于TCP):属于面向连接的通信类型,通信前需通过三次握手建立TCP连接,数据传输具备可靠、有序、无丢失的特点,适用于对数据完整性要求高的场景(如Web服务、文件传输)🔶2-621、🔶2-622; 2. 数据报套接字(基于UDP):属于无连接的通信类型,通信前无需建立连接,直接发送数据报,传输效率高但不保证可靠性与有序性,适用于实时性要求高的场景(如视频流、实时通信)🔶2-621、🔶2-623; 3. 多播套接字(MulticastSocket):支持向多个目标进程同时发送数据,适用于组播通信场景,如多用户实时会议🔶2-621、🔶2-624。

3.6.2 远程过程调用(Remote Procedure Call, RPC)

RPC是客户端-服务器系统中“模拟本地过程调用”的通信机制,通过抽象网络细节,让客户端进程以调用本地函数的方式调用服务器端的过程,具体实现如下: - 核心作用:隐藏网络通信的复杂性(如地址定位、数据传输、错误处理),使客户端无需关注底层网络细节,仅需按本地调用逻辑发起请求,降低分布式编程难度🔶2-630、🔶2-631。 - 关键组件:存根(Stub): - 客户端存根:作为客户端进程与网络的中介,负责定位服务器地址、将调用参数按标准格式“编组(Marshalling)”(打包为网络可传输的消息)、通过网络发送请求至服务器🔶2-634、🔶2-635; - 服务器端存根:作为服务器进程与网络的中介,负责接收客户端消息、将参数“解组(Unmarshalling)”(还原为服务器可识别的格式)、调用实际的服务器过程,并将执行结果按同样逻辑返回给客户端🔶2-634、🔶2-636; - Windows特殊实现:服务器端存根代码可通过Microsoft接口定义语言(MIDL)编写的规范编译生成,确保接口标准化🔶2-637。 - 参数编组与数据表示:参数编组是将客户端参数转换为统一网络格式的过程,为解决不同架构(如大端、小端字节序)的数据兼容性问题,RPC采用外部数据表示(XDR)格式处理数据,确保客户端与服务器间数据格式一致🔶2-645、🔶2-646。 - 服务匹配:操作系统通常提供“rendezvous(匹配)服务”,客户端通过该服务查询目标RPC服务对应的服务器端口号,实现客户端与服务器的动态连接🔶2-649、🔶2-666。

3.6.3 管道(Pipes)

管道在客户端-服务器系统中作为轻量级通信载体,不同操作系统的实现与功能存在差异,具体分为Unix与Windows两类: - Unix系统中的管道: 1. 匿名管道(普通管道):仅支持有父子关系的客户端与服务器进程(如父进程作为服务器、子进程作为客户端),通信方向为单向(半双工),无独立名称,仅通过文件描述符访问,随进程生命周期销毁🔶2-670、🔶2-677; 2. 命名管道:支持无父子关系的客户端与服务器进程通信,通信方向为双向(全双工),有唯一路径名作为标识,任意进程通过路径名即可连接,仅支持同一主机内通信,不支持跨网络🔶2-670、🔶2-692、🔶2-693。 - Windows系统中的管道:核心为命名管道,与Unix命名管道相比,除支持同一主机内客户端-服务器通信外,还具备跨网络通信能力,可通过网络地址定位远程服务器的命名管道,实现不同主机间的客户端-服务器数据交互🔶2-670、🔶2-693。

3.6.4 远程方法调用(Remote Method Invocation, RMI)

RMI是Java语言专属的客户端-服务器通信机制,基于面向对象思想扩展RPC,实现远程对象的方法调用,具体特性如下: - 核心定位:属于“面向对象的RPC”,区别于传统RPC对“过程”的调用,RMI支持客户端直接调用远程服务器端Java对象的方法,完全遵循Java的面向对象编程模型🔶2-608。 - 核心优势:隐藏网络通信细节,客户端无需关注网络传输、地址定位等底层操作,仅需通过远程对象的引用调用方法,就像调用本地对象方法一样;同时支持Java对象的序列化与反序列化,确保复杂对象(如自定义类实例)可在客户端与服务器间传输🔶2-608。 - 适用场景:主要用于Java语言开发的客户端-服务器系统,如Java EE架构中的分布式应用,实现不同主机上Java组件的交互。


附录内容(Appendix,基于类似章节推断,可能在文档后部)

  • Appendix 3.A 进程管理历史
  • 从批处理到分时、多道程序演变。
  • Appendix 3.B Unix/Linux 进程管理
  • fork()、exec()、wait() 示例。
  • ps、top 命令。
  • Appendix 3.C Windows 进程管理
  • CreateProcess()、线程 vs 进程。
  • 虚拟机与容器(可能扩展)
  • 进程隔离:VM vs Docker。

Linux 案例分析与实验(可能在文档末尾,类似上一章)

  • 进程管理 in Linux
  • task_struct (PCB)。
  • 调度:CFS (Completely Fair Scheduler)。
  • IPC:System V IPC (共享内存、信号量、消息队列)、POSIX。
  • 实验
  • 进程创建:编写 fork() 程序。
  • IPC:共享内存/消息队列实现生产者-消费者。
  • 工具:gdb 调试、strace 跟踪系统调用。

章节目标总结(Outline 页,Page 4)

部分 内容
Process Concept 进程介绍:定义、组成、状态。
Process Scheduling 调度:短期/长期/中期,队列。
Operations on Processes 操作:创建、终止。
Interprocess Communication IPC:共享内存、消息传递。
Examples of IPC Systems 示例:POSIX、Mach、Windows。
Communication in Client-Server Systems 客户端-服务器:Sockets、RPC、RMI。

总结:本章聚焦进程作为 OS 核心,层层展开从概念到通信,结合 Unix/Windows/Linux 示例讲解。强调并发、调度和 IPC 的重要性,为后续线程、同步章节奠基。如果需要特定页面的详细内容或图表解释,请提供更多细节!