# 第四章 互斥、同步与通讯(下) ## 一、知识讲解 本章承接第四章(上)的内容,重点介绍**进程高级同步机制(会合)**与**进程高级通讯机制**。低级同步(信号灯、管程)基于共享存储区,难以适应分布式环境;高级机制则更适合分布/异构系统。 --- ### 4.3.6 会合(Rendezvous) #### 1. 会合的引入背景 **Ada 语言**(80年代由美国国防部 DOD 发起,Ada 95 引入面向对象特性)首先提出"会合"作为分布式系统中的同步通讯机制。 - **共享变量方式**:PV 操作(信号灯)依赖于访问进程与共享变量在**同一存储区**。当进程分布在不同站点(站点1、站点2)时,共享内存不可用,无法用 PV 实现互斥。 - **管程方式**:管程是被动的同步原语,但管程本身与调用进程在同一存储区,**不适合分布环境**。 因此,Ada 提出了**会合**机制:两个并发执行流汇集到一处——调用方发起调用,被调用方接受,**握手、同步发生**,且能传递参数。 #### 2. 会合图示 - 任务(被调用者)有多个 entry(入口),每个入口有一个 **FIFO 队列**保存等待的调用者。 - 调用者发起 `调用语句`,被调用任务在 `accept` 处等待。 - 双方在某入口汇合后,由**被调用者代替调用者执行调用代码**(即执行 accept 后面的语句序列)。 - 会合结束后双方各自继续。 #### 3. Ada 同步语句 **(1)调用语句** ``` <任务名称>.<入口名称>[<实参表>] ``` 如:`single_resource.acquire;` **(2)接受语句** ``` accept <入口名称>[<形参表>] [do <语句序列> end <入口名称>] ``` accept 后面跟的 `do...end` 块即为会合期内被调用方执行的代码。 **(3)选择语句 select** ``` select [when <布尔表达式> =>] <接受语句> [<语句序列>] { or [when <布尔表达式> =>] <接受语句> [<语句序列>] } [ else <语句序列>] end select ``` #### 4. accept 语句的执行流程 ``` 有调用者? ├─ 等待 ─→ 选取第一个 └─ 有 ─→ 会合开始 ├─ 调用者等待 ├─ 有 in 参数 ─→ 取 in 参数 ├─ 有语句序列 ─→ 执行之 ├─ 有 out 参数 ─→ 送 out 参数 └─ 会合结束 ─→ 调用者继续 ``` 只有当**调用者与被调用者双方都到达会合点**时,会合才开始;任一方先到则等待对方。 #### 5. select 语句语义(要点) 1. 计算所有 `when` 后的布尔表达式,**为真者对应入口标记为"开放"**。 2. **若没有开放的 accept**: - 若有 `else` 部分,执行 else;否则抛异常(程序退出 select)。 3. **若没有"开放且被调用的" accept**: - 若有 `else`,执行 else;否则**等待**直到有调用者出现。 4. **任取一开放且被调用的 accept**,进入会合期,执行参数传递与会合代码。 5. 会合结束后,若 select 后有语句序列,则继续执行。 #### 6. 典型例子——单一资源管理 ```ada task single_resource is entry acquire; entry return; end single_resource; task body single_resource is begin loop accept acquire; accept return; end loop end single_resource; -- 使用方 single_resource.acquire; -- 使用资源 single_resource.return; ``` **说明**:因为 `accept` 之间是顺序的,所以 acquire 与 return 必须交替执行,天然保证了互斥。 #### 7. 客栈问题(Ada Lodge Problem)——会合综合应用 场景:猎人(hunter)送来一份猎物,面包师(bakery)送来一份面包,主人(master)把面包+猎物做成三明治,探险家(explorer)进店取走一份三明治吃。**一份猎物 + 一份面包 = 一份三明治**。 关键设计: - master 任务有三个 entry:`deliverbread`、`delivermeat`、`lodge`。 - select 中: - `when bread=0` 接受面包; - `when meat=0` 接受猎物; - `when (sandwich<>0) or (bread<>0 and meat<>0)` 接受探险家入店请求; - else 分支:当"有面包且有猎物且没三明治"时调用 `makesandwich`(栈主人主动做三明治)。 要点:**会合期外仍可执行语句**(如 `sandwich:=0`、`makesandwich`),select 的 else 分支就属于"会合期外"。 #### 8. 有界缓冲问题(Bounded Buffer) ```ada task boundedbuffer is entry putin; entry getout; end boundedbuffer; task body boundedbuffer is b: array(0..k-1) of integer; ip, op: 0..k-1; count: integer; begin ip:=0; op:=0; count:=0; loop select when (count accept putin(item:in integer) do b(ip):=item end putin; ip:=(ip+1) mod k; count:=count+1; or when (count>0) => accept getout(item:out integer) do item:=b(op) end getout; op:=(op+1) mod k; count:=count-1; end select end loop end boundedbuffer; ``` 通过 `when` 守卫保证缓冲区满时拒绝 putin、空时拒绝 getout。 #### 9. 读者-写者问题(写者优先,作业#4) ```ada task readers_writers is entry start_read, finish_read; entry start_write, finish_write; end readers_writers; task body readers_writers is read_count, write_count: integer; begin read_count:=0; write_count:=0; loop select when write_count=0 => accept start_read do read_count:=read_count+1; end start_read or when read_count>0 => accept finish_read do read_count:=read_count-1; end finish_read or when write_count=0 => accept start_write do while read_count>0 do accept finish_read do read_count:=read_count-1; end finish_read end while end start_write; write_count:=write_count+1 or when write_count>0 => accept finish_write do write_count:=write_count-1; end finish_write end select end loop end readers_writers; ``` **写者优先的关键**:在 `accept start_write` 内**嵌套 accept finish_read**,把当前所有读者"消化"完后再把 `write_count` 加1,从而阻止后续新读者进入。 --- ### 4.4 进程高级通讯 #### 1. 进程通讯的层次 | 层次 | 通讯内容 | 机制 | |------|----------|------| | **低级通讯** | 简单信号(少量控制信息) | 进程互斥、进程同步(如 PV) | | **高级通讯** | 大宗信息(数据/消息) | 共享内存、消息传递 | #### 2. 高级通讯的分类(重要考点) | 维度 | 类别 1 | 类别 2 | |------|--------|--------| | **通讯机制** | 共享内存(memory sharing) | 消息传递(message passing) | | **寻址方式** | 直接(进程-进程) | 间接(进程-信箱-进程) | | **命名对称性** | 对称(sender 和 receiver 互相指名) | 非对称(仅 sender 指名 receiver) | | **缓冲方式** | 有缓冲 | 无缓冲 | --- ### 4.4.2 进程通讯模式 #### 1. 共享内存模式(Shared Memory) - OS 提供**一段公共内存区 M**。 - 进程 P1、P2 通过 `P/V` 等互斥同步机制保证对 M 的安全访问。 - 适用于单机多进程,效率高;但**不能跨越机器**。 #### 2. 消息传递模式(Message Passing) - 进程间通过 `send / receive` 原语交换消息。 - 可分布式、跨网络;是分布式 OS 的主要通讯手段。 --- ### 4.4.3 直接方式 #### 1. 对称形式(Symmetric) ``` send(R, message) receive(S, message) ``` 发送方和接收方**互相指名**对方。优点是清晰;缺点是进程名变化时双方都要改。 #### 2. 非对称形式(Asymmetric,仅 sender 指名) ``` send(R, message) receive(pid, message) ``` 只有发送者指名接收者,接收者由 `pid`(任一发送者)反向得到。常见于 **C/S 模型**:多个 client(sender)向 server(receiver)发请求。 --- ### 4.4.3.1 有缓冲途径(直接方式、非对称、有缓冲) #### 1. 消息结构 ``` size | text | sender | link ``` #### 2. 进程消息队列管理(每接收者一个队列) ``` Var Sm: semaphore; -- 初值 0(队列中消息计数) Var m_mutex: semaphore; -- 初值 1(队列互斥) ``` - 接收方 `receive` 前:`P(Sm)`。 - 发送方 `send` 后:`V(Sm)`。 - 入列/出列动作夹在 `P/V(m_mutex)` 之间。 #### 3. 缓冲池管理 ``` Var Sb: semaphore; -- 初值 k(空缓冲数量) Var b_mutex: semaphore; -- 初值 1(缓冲池互斥) Head:缓冲链头 ``` 申请空缓冲:`P(Sb); P(b_mutex); 头缓冲出链; V(b_mutex);` 释放空缓冲:`P(b_mutex); 缓冲入链头; V(b_mutex); V(Sb);` #### 4. send / receive 原语伪码 ``` Send(R, M): 根据R找接收者 P(Sb); P(b_mutex); 取一空buf; V(b_mutex); buf <- (size, text, sender) P(m_mutex); 消息入链尾; V(m_mutex); V(Sm); Receive(pid, N): P(Sm); P(m_mutex); 头消息出链; V(m_mutex); (size, text) -> N; sender -> pid P(b_mutex); 空buf入链; V(b_mutex); V(Sb); ``` **重要说明**:send/receive 本身是高级通讯原语,但**它们可以用低级原语(PV)来实现**;而且 send/receive 并不是"真正不可中断"的原语,OS 在执行它们的过程中仍可能被中断。 --- ### 4.4.3.2 无缓冲途径(直接方式、非对称、无缓冲) #### 1. 实现机制 - 收发双方 PCB 各有两个信号灯 `S_m`、`S_w`,初值都为 0。 - **不设缓冲**,消息由发送者进程空间直接**复制**到接收者进程空间。 - 必须收发双方**同时到达会合点**(会合性/rendezvous 语义)。 #### 2. send 过程 ``` Send(R, M): 根据R找到消息接收者 发送消息进程计数+1 若接收进程在等待则将其唤醒 → V(S_m) 等待消息传送完毕 → P(S_w) ``` #### 3. receive 过程 ``` Receive(pid, N): 等待消息到达 → P(S_m) 消息由发送进程空间复制到接收进程空间 唤醒发送消息进程 → V(S_w) ``` #### 4. 优缺点对比 | 优点 | 缺点 | |------|------| | 节省空间(不需要 buffer) | 并发性差:发送方必须等接收方 receive 完成复制后才能继续 | --- ### 4.4.4 间接方式(Mailbox / 信箱) #### 1. 概念 进程间通讯通过一个**共享信箱 mb** 进行: ``` Send_mb(mb, m) Receive_mb(mb, n) ``` 拓扑灵活: - 多对一(多 sender — 一 receiver,如服务器场景) - 多对多(多 sender — 多 receiver) #### 2. 信箱数据结构(属于 OS 空间) ``` type mailbox = record in, out: 0..k; -- 环形队列指针 s1, s2: semaphore; -- s1 初值 k(空位数),s2 初值 0(消息数) mutex: semaphore; -- 初值 1 letter: array[0..k-1] of message; end; var mb: mailbox; ``` 系统调用 `create_mb(mb)`、`delete_mb(mb)` 创建/销毁信箱。 #### 3. send_mb / receive_mb 实现 ``` Procedure send_mb(var mb: mailbox; m: message): P(s1); -- 申请空位 P(mutex); letter[in] := m; in := (in+1) mod k; V(mutex); V(s2); -- 消息数 +1 Procedure receive_mb(var mb: mailbox; var n: message): P(s2); -- 申请消息 P(mutex); n := letter[out]; out := (out+1) mod k; V(mutex); V(s1); -- 空位数 +1 ``` **关键点**: - `s1`、`s2` 一对信号灯实现了**生产者-消费者**约束(空位 vs 消息)。 - `mutex` 实现对信箱内部数据结构的互斥访问。 - 信箱属于 OS 空间,由 OS 统一管理生命周期。 #### 4. 信箱空间归属小结 | 归属 | 说明 | 生命周期 | |------|------|----------| | **OS 空间**(如上) | 由 OS 创建/销毁 | 进程结束信箱仍可保留 | | 进程空间 | 由某进程创建,进程退出即失效 | 与进程同生共死 | --- ### UNIX 进程高级通讯机制 #### 1. 管道(Pipe) - 基于**文件系统**实现,与普通文件使用统一的界面(open/read/write/close)。 - **两次 IO**:读、写各一次。 - **速度优化**: - **延迟写(delayed write)**:先写到内存缓冲区,内存资源不紧张且缓冲区不被占用时不会刷到外存。 - 读时优先从内存缓冲区得到数据。 - **大小限制**:通常 ~2KB;超出后循环使用,避免缓冲资源紧张。 - 适用:父子/兄弟进程等**有亲缘关系**的进程(无名管道)。 #### 2. UNIX 信号(Signal) - 每个进程 PCB 中有 `p_sig` 字段记录接收到的信号。 - user 结构中有 `u_signal[NSIG]` 数组保存信号处理程序入口。 - 系统调用 `signal(sig, func)` 预置处理程序: - `func = 0`:收到信号时进程**终止自己**。 - `func = 奇数`:**忽略**该信号。 - `func = 偶数`:作为**处理程序入口地址**。 - 子进程**继承**父进程的信号处理程序。 - 信号**任何时候都可接收**,仅记录在 `p_sig` 中。 - 信号**处理时机**:进程被调度选中、即将由**核心态转为目态(用户态)**时。 - 信号对用户而言是一种"软中断"。 --- ### Windows 10 的管道 | 类型 | 命名 | 标识 | 关键 API | |------|------|------|----------| | **无名管道**(Anonymous) | 无 | 句柄 `hReadPipe`、`hWritePipe` | `CreatePipe` | | **命名管道**(Named) | `\\.\pipe\PipeName`(服务端)/ `\\serverName\pipe\PipeName`(客户端) | 文件系统路径 | `CreateNamedPipe`、`ConnectNamedPipe`、`CallNamedPipe`、`ReadFile`/`WriteFile` | - **CreateNamedPipe**:服务器端建立管道。 - **ConnectNamedPipe**:服务器端等待客户连接请求。 - **CallNamedPipe**:客户端建立到服务器管道的连接并通讯。 - **ReadFile / WriteFile**:管道读写(与文件 I/O 同一套接口)。 --- ### Windows 10 的 Mailslot(邮件槽) - **服务端路径**:`\\.\mailslot\[path]name`(本地) - **客户端路径**:`\\range\mailslot\[path]name`(range 是域名,表示发往哪台主机) - 关键 API: - `CreateMailslot`:服务端创建邮件槽。 - `GetMailslotInfo`:服务端查询邮件槽状态(消息数、最大长度等)。 - `ReadFile`:服务端读取消息。 - `WriteFile`:客户端发送消息。 **特点**:基于广播/域内投递,适合**一对多**的轻量级消息通讯。 --- ### 概念对比小结(考试最爱) | 机制 | 拓扑 | 缓冲 | 同步性 | 适合场景 | |------|------|------|--------|----------| | **共享内存** | 1 对 1 或多对多 | 用户自管 | 用户自管 | 单机高速数据交换 | | **直接消息 有缓冲** | 1 对 1 或多对 1 | OS 维护消息队列 | 异步(发送后即可返回) | C/S、Producer-Consumer | | **直接消息 无缓冲** | 1 对 1 | 无 | **会合(同步)** | 强同步握手 | | **间接消息(信箱)** | 多对 1 / 多对多 | OS 信箱 | 异步 | 多发送者场景、解耦 | | **管道** | 通常 1 对 1(亲缘) | 内核缓冲 | 字节流 | shell 流水线 | | **命名管道** | C/S | 内核缓冲 | 同步/异步 | 跨进程、跨网络(Windows) | | **邮件槽 mailslot** | 多对多(域) | 内核 | 不可靠/单向 | Windows 局域网广播 | --- ## 二、考点总结 ### 考点1:会合(Rendezvous)的概念与适用场景 - **内容**:会合是 Ada 语言提出的、用于**分布式系统**的同步通讯机制。两个并发执行流在"调用语句"与"accept 语句"处汇合,握手、同步发生,由被调用方代替调用方执行会合代码。引入背景是共享变量/管程无法在分布式站点间使用。 - **考查方式**:选择、填空、简答。 - **可能的题目**: 1. (填空)会合机制是为解决 __________ 环境下共享变量与管程不可用的问题而提出的。 - 答案:**分布式(多站点)** 2. (简答)为什么共享变量方式(PV)不适合分布式系统? - 答案:PV 操作的共享变量必须与访问进程位于**同一存储区**;分布式系统中各进程分布在不同站点,没有共享内存,因此无法用 PV 实现互斥/同步。 ### 考点2:Ada 的三类同步语句 - **内容**:调用语句 `<任务>.<入口>[<实参>]`;接受语句 `accept <入口>[<形参>] [do <语句序列> end <入口>]`;选择语句 `select ... or ... [else ...] end select`。 - **考查方式**:填空、简答、代码阅读。 - **可能的题目**: 1. (填空)Ada 中被调用任务用以接受调用请求的语句是 __________。 - 答案:**accept 语句** 2. (代码)写出单一资源管理器的 Ada task 框架。 - 答案:见上文"单一资源管理"示例,含 `accept acquire; accept return;` 顺序循环。 ### 考点3:accept 的会合期执行流程 - **内容**:调用者发起调用→任务在 accept 等待→双方到齐会合开始→若有 in 参数则取 in 参数→若有语句序列则执行→若有 out 参数则送 out 参数→会合结束,调用者继续。 - **考查方式**:选择、流程图题。 - **可能的题目**: 1. (选择)关于 accept 语句,下列说法正确的是:__ - A) 仅调用者到达会合点即可开始会合 - B) 仅被调用者到达会合点即可开始会合 - C) **双方都到达会合点时才会合才开始**(正确答案) - D) 会合由调用方执行会合代码 ### 考点4:select 语句的语义(when / else / 等待) - **内容**:先算所有 `when` 布尔式,为真者对应入口开放;若没有开放 accept 且无 else 则异常;若没有"开放且被调用的" accept 则等待(或执行 else);任选一开放且被调用的 accept 执行会合。 - **考查方式**:选择、读程序、写程序。 - **可能的题目**: 1. (选择)select 语句中若所有 when 条件都为假、且没有 else 部分,则行为是:__ - 答案:**抛异常(异常退出 select)** 2. (选择)若所有开放入口都无调用者、且没有 else,则行为是:__ - 答案:**等待**直到有调用者出现 ### 考点5:会合的典型应用——客栈问题 - **内容**:master 任务的三个 entry(deliverbread、delivermeat、lodge)通过 select 的 when 守卫实现"一份面包 + 一份猎物 = 一份三明治"的同步约束,else 分支在会合期外主动 `makesandwich`。 - **考查方式**:代码补全、简答。 - **可能的题目**: 1. (简答)客栈问题中 master 如何保证每次只做一份三明治? - 答案:通过 `sandwich`、`bread`、`meat` 三个状态变量 + select 的 when 守卫实现:lodge 入口需 `sandwich≠0 或 (bread≠0 且 meat≠0)`;else 分支在原料齐备时主动制作。做完/取走后立即清零。 ### 考点6:会合的典型应用——有界缓冲问题 - **内容**:用 count 与模 k 的环形缓冲,通过 select 的 `when count0` 实现生产者-消费者约束。 - **考查方式**:选择、改写。 - **可能的题目**: 1. (选择)Bounded buffer 的 putin 入口的守卫条件是 ________。 - 答案:`count < k`(缓冲区未满) ### 考点7:会合实现读者-写者问题(写者优先) - **内容**:用 `read_count`、`write_count` 计数;在 `accept start_write` 内**嵌套 accept finish_read**,把所有活跃读者消化完后再使 write_count 加 1,从而阻止后续新读者。 - **考查方式**:代码阅读、简答。 - **可能的题目**: 1. (简答)为什么把 `accept finish_read` 嵌套在 `accept start_write` 内部即可实现"写者优先"? - 答案:嵌套的 accept 在会合期内会持续接收并处理读者退出请求,直到 `read_count=0`,然后会合结束、写者才能进入并把 `write_count` 增 1。这样在已有写者等待时,新读者被 `when write_count=0` 守卫阻挡,无法进入,从而保证写者优先。 ### 考点8:进程高级通讯的分类 - **内容**:高级通讯按四种维度分类:共享内存 vs 消息传递;直接 vs 间接;对称 vs 非对称;有缓冲 vs 无缓冲。 - **考查方式**:选择、填空、简答。 - **可能的题目**: 1. (填空)高级通讯的两大机制是 __________ 和 __________。 - 答案:**共享内存(memory sharing)**、**消息传递(message passing)** 2. (选择)C/S 模型中常见的是哪种命名方式? - A) 对称形式 B) **非对称形式(仅 sender 指名 receiver)**(正确答案) ### 考点9:直接消息——有缓冲途径的 PV 实现 - **内容**:每接收者维护消息队列,需要三组信号灯:`Sm`(消息计数,初值0)、`m_mutex`(队列互斥,初值1)、`Sb`(空缓冲数,初值k)、`b_mutex`(缓冲池互斥,初值1)。send 时申请空 buf、填入消息、入队、`V(Sm)`;receive 时 `P(Sm)`、出队、归还 buf、`V(Sb)`。 - **考查方式**:代码补全、PV 计算、应用题。 - **可能的题目**: 1. (填空)有缓冲消息队列中,`Sm` 的初值是 ________,`m_mutex` 的初值是 ________。 - 答案:`Sm=0`,`m_mutex=1` 2. (应用)画出 `send(R,M)` 完整 PV 序列。 - 答案:`P(Sb); P(b_mutex); 取空buf; V(b_mutex); 填 buf; P(m_mutex); 入队; V(m_mutex); V(Sm);` ### 考点10:直接消息——无缓冲途径(会合语义) - **内容**:收发双方各设 `S_m`、`S_w`(初值0)。发送方 `V(S_m)` 后 `P(S_w)` 等待;接收方 `P(S_m)` 后复制消息,再 `V(S_w)`。**消息直接从发送进程空间复制到接收进程空间**,无需缓冲。 - **考查方式**:PV 顺序题、简答。 - **可能的题目**: 1. (填空)无缓冲途径下,发送方发送消息后必须执行 __________ 才能继续。 - 答案:`P(S_w)`(等待接收方复制完消息) 2. (简答)无缓冲途径相对有缓冲途径的优缺点。 - 答案:优点——节省空间(不需要缓冲);缺点——并发性差,发送方必须等接收方执行 receive 把消息复制到接收进程空间后才能继续。 ### 考点11:间接方式——信箱通讯 - **内容**:信箱属于 OS 空间,含环形队列 `letter[in..out]`、信号灯 `s1`(空位=k)、`s2`(消息=0)、`mutex`(互斥=1)。send_mb:`P(s1); P(mutex); letter[in]:=m; in++; V(mutex); V(s2);`。receive_mb:反向。 - **考查方式**:PV 顺序、代码补全。 - **可能的题目**: 1. (填空)信箱通讯中 `s1` 表示 ________、`s2` 表示 ________。 - 答案:`s1` 表示**空位数**(初值k),`s2` 表示**消息数**(初值0) 2. (选择)信箱机制最适合的场景是: - A) 1对1 同步握手 B) **多对一 或 多对多,解耦发送者和接收者**(正确答案) ### 考点12:UNIX 管道(Pipe) - **内容**:基于文件系统、与文件统一界面;速度优化包括**延迟写**(写到内存缓冲,不立刻刷盘)和**大小限制**(如2KB,循环使用);通常用于亲缘进程(无名管道)。 - **考查方式**:选择、填空、简答。 - **可能的题目**: 1. (填空)UNIX pipe 的速度优化措施有 ________ 和 ________。 - 答案:**延迟写(delayed write)**、**缓冲大小限制(循环使用)** 2. (简答)为什么 pipe 虽然是"文件"但一般不会真的执行磁盘 I/O? - 答案:pipe 采用延迟写策略,数据先写入内存缓冲区,内存资源不紧张时不会刷盘;读时直接读内存缓冲,因此基本不发生磁盘 I/O。 ### 考点13:UNIX 信号(Signal) - **内容**:`p_sig` 字段记录收到的信号;`u_signal[NSIG]` 数组保存处理入口;`signal(sig,func)` 中 func=0 终止、奇数忽略、偶数为处理入口;子进程继承父进程信号表;信号处理时机是**由核心态转目态前**。 - **考查方式**:选择、填空。 - **可能的题目**: 1. (填空)UNIX 中,进程被调度选中即将由核心态转为目态时,会检查并处理 PCB 中的 ________ 字段。 - 答案:`p_sig`(信号字段) 2. (选择)`signal(sig, func)` 中 `func` 为奇数表示:__ - A) 终止进程 B) **忽略该信号**(正确答案) C) 作为处理入口 D) 出错 ### 考点14:Windows 命名管道 vs 无名管道 - **内容**:无名管道通过 `CreatePipe` 创建,仅本机有亲缘关系的进程可用;命名管道使用路径名 `\\.\pipe\PipeName` 或 `\\serverName\pipe\PipeName`,可跨网络,支持 C/S,关键 API 有 `CreateNamedPipe`、`ConnectNamedPipe`、`CallNamedPipe`、`ReadFile/WriteFile`。 - **考查方式**:选择、填空、应用。 - **可能的题目**: 1. (填空)Windows 中,命名管道服务端路径格式为 ________,客户端为 ________。 - 答案:`\\.\pipe\PipeName`、`\\serverName\pipe\PipeName` 2. (选择)下列哪个 API 是客户端用来连接命名管道的? - 答案:`CallNamedPipe` ### 考点15:Windows Mailslot(邮件槽) - **内容**:服务端 `\\.\mailslot\[path]name`,客户端 `\\range\mailslot\[path]name`;支持一对多的轻量级不可靠消息通讯;API:`CreateMailslot`、`GetMailslotInfo`、`ReadFile`、`WriteFile`。 - **考查方式**:选择、填空。 - **可能的题目**: 1. (填空)邮件槽主要适用于 ________ 的消息通讯场景。 - 答案:**一对多(域内广播)/ 轻量级消息** 2. (选择)服务端查询邮件槽状态应调用:__ - 答案:`GetMailslotInfo` ### 考点16:综合——各通讯机制对比 - **内容**:共享内存 vs 消息传递、直接 vs 间接、有缓冲 vs 无缓冲、管道 vs 命名管道 vs mailslot 在拓扑、同步性、缓冲、典型场景上的差异。 - **考查方式**:表格题、简答。 - **可能的题目**: 1. (简答)比较"直接消息 无缓冲"与"直接消息 有缓冲"在同步性、空间开销、并发性上的差异。 - 答案:① **同步性**:无缓冲是会合式(同步,必须同时到达);有缓冲是异步(send 后即可返回)。② **空间**:无缓冲不需要缓冲,节省空间;有缓冲需要缓冲池(开销=k 个缓冲 + 队列)。③ **并发性**:无缓冲并发性差(发送方必须等待接收方 receive 复制完成);有缓冲并发性好(消息进入队列即返回)。 2. (简答)比较消息传递与共享内存的优缺点。 - 答案:消息传递——易于分布式、跨网络,编程简单,但有数据拷贝开销;共享内存——效率高(无拷贝)、适合大数据量,但必须自行解决互斥同步,且**不适合分布式**。