RFC 7 带读:Host-IMP Interface——从用户请求到硬件中断,ARPANET 主机网络栈的早期分层

前言

读完 RFC 6 以后,Host 与 IMP 之间“到底应该怎么接”仍然只是一些散落的问题:

  • 字符转换由谁完成;
  • Host 应该向 IMP 提供哪些控制信息;
  • IMP 应该怎样反馈状态;
  • Link 字段到底多大;
  • 出错以后谁负责处理。

到了 RFC 7,这些讨论第一次明显地收敛成一份软件组织设计草案

RFC 7 的标题非常直接:

Host-IMP Interface

作者 Gérard Deloche 没有试图重新定义整个 ARPANET,而是盯住 UCLA Host 这一侧,回答一个更接近系统软件实现的问题:

一个用户程序想通过 ARPANET 发数据时,Host 操作系统内部到底应该有哪些程序、数据结构和硬件接口,把这个请求一路送到 IMP?

RFC 7 给出的核心结构只有两个主要程序:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
User Programs


Network Program

├── Buffer Pool
└── Interface Table


Handler Program


Channel Hardware


IMP

其中:

  • **Network Program(网络程序)**面向用户请求,负责多路复用、消息封装、长度检查、分片、字符转换和缓冲;
  • **Handler Program(处理程序)**面向硬件,运行在特权模式,负责驱动通道设备、处理中断、搬运缓冲区和维护接口状态。

如果用今天的词汇做一个谨慎的类比:

1
2
3
4
5
6
7
8
9
10
11
Network Program
≈ 协议栈 / 网络子系统较上层的软件逻辑

Handler Program
≈ 底层设备驱动 / I/O Handler

Buffer Pool
≈ 共享数据缓冲区

Interface Table
≈ 软件层与驱动层之间的描述符队列

但这只能帮助理解。

RFC 7 不是 Linux 网络栈,也不是现代 socket + driver 架构的直接原型。它面对的是 1969 年 UCLA 的 SDS Sigma 7 和一台即将接入 ARPANET 的 IMP。

更重要的是,RFC 7 自己就明确说它只是:

preliminary software design(初步软件设计)

而且它的最后一章不是“Conclusion”,而是:

Questions

其中还留着几个非常关键、尚未解决的问题:

1
2
3
4
5
Host 与 IMP 为什么没有更直接的控制过程?
Host→IMP 传输过程中出错,到底由谁发现和恢复?
Handler 怎样知道输入消息真实长度?
特殊通道硬件如何配合 padding?
用户程序怎样调用 Network Program?

所以 RFC 7 最值得今天的软件开发者阅读的地方,并不是记住一个 16-bit Header。

而是观察:

一个网络协议概念,怎样开始变成操作系统里的程序、队列、缓冲区、系统调用、特权代码和硬件中断。

RFC 基本信息

项目 内容
RFC RFC 7
官方英文标题 Host-IMP interface
作者 G. Deloche(Gérard Deloche)
所属机构 University of California at Los Angeles(UCLA)
文档日期 May 1969
RFC 100 记录日期 5 May 1969
研究对象 ARPANET Host-IMP Interface Programs
参考基础 BBN Report No. 763
RFC Editor 当前状态 Unknown
1971 年历史分类 Obsolete
RFC Editor 信息页 RFC 7: Host-IMP interface
RFC 原文 RFC 7 原文

这是一份“抢救式重建”的历史文档

RFC 7 有一个必须先知道的档案问题。

RFC Editor 在正文开头专门说明:

  • 原始 RFC 7 是手写稿
  • 留存下来的副本部分字迹已经无法辨认;
  • 后来 SRI 的 **Augmentation Research Center(ARC)**在 NLS 中重新录入;
  • 今天看到的机器可读文本,是基于现有材料做出的最佳重建。

因此正文中可以看到:

1
...(unreadable)

之类的标记。

这意味着 RFC 7 与现代 RFC 有根本不同:

1
2
3
4
5
6
7
8
9
现代 RFC:
正式电子源文件
→ 精确归档

RFC 7:
手写原稿
→ 模糊副本
→ 人工重录
→ 后期机器可读重建

所以阅读过程中,如果发现:

  • 拼写错误;
  • 图形错位;
  • 某些句子缺字;
  • 术语前后略有不一致;

首先要考虑的是:

这可能是历史文档保存问题,而不是某个已经精确定义的协议细节。

RFC 7 很快就过时了

1971 年的 RFC 100 对 RFC 7 的记录非常简洁:

1
2
3
4
5
6
NWG/RFC 7
HOST/IMP Interface
G. Deloche (UCLA)
5 May 1969

Obsolete

这和 RFC 7 自己“preliminary”的定位完全一致。

它不是后来长期运行的 Host-IMP Interface 标准,而是一份早期 UCLA 实现草案。

不过它仍然非常有价值,因为它保存了:

Host 网络软件从概念转向具体操作系统实现的一个中间状态。

为什么会有这篇 RFC

一、RFC 1~6 讨论了网络,但“谁来写代码”越来越现实

RFC 1 和 RFC 2 已经提出:

  • Host Software;
  • Link;
  • Control Link;
  • TTY-like communication;
  • File-like communication;
  • Host-to-Host error checking。

RFC 6 又讨论:

  • IMP 是否做字符转换;
  • Tracing;
  • RFNM;
  • Host / IMP 状态;
  • Format Error;
  • Synchronization。

这些都是协议层面的讨论。

但真正部署时,UCLA 需要面对一台具体的 Sigma 7:

1
2
3
4
5
6
7
用户程序调用什么?
谁组织 Message?
谁做 EBCDIC → ASCII?
谁控制通道硬件?
中断到了谁处理?
多用户同时发数据怎么办?
缓冲区如何排队?

RFC 7 就是在这个阶段出现的。

二、ARPANET 的 Host 不是一台“专用网络设备”

Host 是一台正在运行时间共享操作系统的大型计算机。

它本来已经要处理:

  • 用户任务;
  • 文件系统;
  • 编译器;
  • 终端;
  • 调度;
  • I/O。

网络只是新增的一类 I/O 和系统服务。

所以网络软件不能简单写成:

1
2
3
while true:
read_user()
send_to_imp()

它必须融入操作系统现有架构。

RFC 7 因而很自然地把网络软件拆成:

1
2
3
用户语义较强的软件层
+
设备语义较强的硬件处理层

三、多用户共享一条物理网络接口,需要 Multiplexing

RFC 7 的一个核心词是:

Multiplex(多路复用)

同一台 Host 上同时可能有多个用户:

1
2
3
4
User A
User B
User C
User D

它们都想通过同一个 Host-IMP Interface 发消息。

于是必须存在:

1
2
3
4
User A ─┐
User B ─┼─> Network Program ─> Handler ─> IMP
User C ─┤
User D ─┘

Network Program 要把这些请求排起来,再持续填充缓冲区,让 Handler 保持工作。

反向接收时则需要:

1
2
3
4
5
6
7
8
IMP

Handler

Network Program
├── User A
├── User B
└── User C

这就是:

1
2
3
Multiplexing
+
Demultiplexing / Distribution

RFC 7 把它建立在 Link Identification Number 上。

四、软件层和硬件层之间需要明确边界

如果 Network Program 直接控制所有硬件细节:

1
2
3
4
5
设备状态
中断
data chaining
channel start
padding

那么上层协议逻辑会和具体设备紧密耦合。

RFC 7 因此增加 Handler:

1
2
3
4
5
6
7
8
9
Network Program

│ logical information + buffers

Handler

│ hardware commands

Channel Hardware

这正是 RFC 7 最核心的架构选择。

五、这份设计并没有假装所有问题都已经解决

RFC 7 的第三章直接叫:

1
Questions

作者明确承认还有几个关键接口没有搞清楚。

这符合 RFC 3 所倡导的早期 RFC 文化:

1
2
3
4
不必等到全部成熟
先把设计写出来
把问题公开
让其他人继续讨论

RFC 7 本身就是这种工作方式的优秀样本。

核心内容

RFC 7 的正文可以压缩成三层结构:

1
2
3
4
5
6
7
8
9
I. Introduction

II. Scope of the software organization
├── Network Program
├── Handler Program
├── Buffers
└── Interface Table

III. Questions

从软件架构角度,则可以整理成:

flowchart LR
    U[User Programs]
    NP[Network Program]
    BP[Buffer Pool]
    IT[Interface Table]
    HP[Handler Program]
    HW[Channel Hardware]
    IMP[IMP]

    U -->|Transmission Request| NP
    NP -->|Fill| BP
    NP -->|Logical Info| IT
    IT --> HP
    BP --> HP
    HP -->|Commands / Data| HW
    HW --> IMP
    IMP --> HW
    HW -->|Interrupt| HP
    HP --> BP
    HP --> IT
    NP -->|Distribute Input| U

一、两个核心程序

RFC 7 的软件组织建立在两个主要程序上。

Network Program

负责:

1
2
3
4
5
6
7
8
9
10
用户网络请求
消息组织
多路复用
输入分发
消息封装
长度检查
大文本拆分
字符转换
填充 Buffer
维护 Interface Table

它更接近:

面向通信语义的软件层。

Handler Program

负责:

1
2
3
4
5
6
7
8
驱动 Channel Hardware
启动发送
Data Chaining
读取设备状态
处理中断
消费 Buffer
维护 Interface Table
可选的 Host-IMP Control Procedure

它更接近:

面向具体设备和中断机制的软件层。

二、Full Duplex 让两层都要同时考虑 Input / Output

RFC 7 明确指出通信是:

1
full duplex

所以 Network Program 和 Handler Program 都可以逻辑上拆成:

1
2
Output Half
Input Half

即:

flowchart LR
    subgraph NetworkProgram[Network Program]
        NO[Output / Multiplex]
        NI[Input / Distribution]
    end

    subgraph HandlerProgram[Handler Program]
        HO[Output Handler]
        HI[Input Handler]
    end

    NO --> HO
    HI --> NI

文档主要讨论输出方向。

输入方向被认为会有相似结构。

三、Network Program 的 Multiplex Function

Network Program 会把所有用户的发送请求排起来:

1
2
3
4
User 1 Request
User 2 Request
User 3 Request
...

并填充 Buffer Pool。

目标是让底层发送单元持续有数据可处理。

这背后已经出现了一个非常经典的生产者—消费者问题:

1
2
3
4
5
6
7
8
Producer:
Network Program

Queue / Shared Storage:
Buffers + Interface Table

Consumer:
Handler

而反向接收则是:

1
2
3
Handler
→ Network Program
→ correct user

RFC 7 把 Link 描述为两个用户之间的逻辑连接。

Network Program 根据:

1
Link Identification Number

决定:

  • outgoing message 属于哪个逻辑通信;
  • incoming message 应该交给哪个用户。

后续 Host-Host Protocol 会继续调整:

1
2
3
4
Link
Connection
Process
Socket

这些抽象之间的关系。

所以不要把 RFC 7 的定义当成后来 NCP 的最终定义。

五、用户发数据时只需要提供三个核心参数

RFC 7 假设用户程序通过:

1
macro

或者:

1
call parameters

告诉 Network Program:

1
2
3
text location
text length in bytes
destination

即:

参数 意义
Text Location 用户数据在内存中的地址
Text Length 数据长度,单位 byte
Destination 目标 Host

从今天看很像:

1
send(buffer, length, destination)

但 RFC 7 还不是 socket API。

它只是已经开始建立:

用户程序不必自己驱动网络硬件,而是调用操作系统提供的网络服务。

六、16-bit Host Heading

Network Program 会构造一个:

1
16-bit Host Heading

字段如下:

字段 长度
Trace 1 bit
Spare 2 bits
Link Identification Number 8 bits
Destination Host 5 bits
Total 16 bits

可以表示为:

1
2
3
4
5
+-------+----------+--------------------------+-------------------+
| Trace | Spare 2b | Link ID 8b | Destination 5b |
| 1b | | | |
+-------+----------+--------------------------+-------------------+
1 2 8 5

总计:

1
1 + 2 + 8 + 5 = 16 bits

这和 RFC 1 的字段宽度重新对上:

1
2
3
4
Trace        1
Spare 2
Link 8
Destination 5

也和 RFC 6 短暂提到的:

1
five bit link field

形成明显反差。

这再次证明早期接口并未冻结。

七、为什么还要一个 16-bit Marking

除了 16-bit Heading,RFC 7 还在 Header 和 Text 之间插入:

1
16-bit Marking

其形式可以理解为:

1
0000000000000001

也就是在正文第一位之前放一个 1,前面用 15 个 0 补齐。

目的不是业务标识,而是:

让 Text 从 Host 的 word boundary 开始。

对于今天习惯 byte stream 的开发者,这很陌生。

但 Sigma 7 这样的系统高度依赖机器字边界。

所以消息布局并不只是:

1
protocol field design

还要兼顾:

1
machine word alignment

八、最大用户文本为什么是 1006 bytes

RFC 7 给出:

1
Maximum Host Message Length = 8080 bits

其中:

1
2
Heading = 16 bits
Marking = 16 bits

所以留给用户 Text:

1
2
8080 - 32
= 8048 bits

换算成 8-bit byte:

1
2
8048 / 8
= 1006 bytes

因此:

1
Max Text = 1006 bytes

九、超过 1006 bytes 时由 Network Program 分成多个 Message

如果用户文本大于:

1
1006 bytes

Network Program 会拆成多条 Message。

例如:

flowchart LR
    A[User Text<br/>2500 bytes]
    B[Network Program]
    M1[Message 1<br/>1006 bytes]
    M2[Message 2<br/>1006 bytes]
    M3[Message 3<br/>488 bytes]

    A --> B
    B --> M1
    B --> M2
    B --> M3

RFC 7 还提出:

可以考虑使用一个 Spare bit,表示多个 Message 属于同一段 Text。

这是一个非常早期的:

1
message fragmentation / grouping metadata

思路。

但它只是 Remark,不是已经敲定的正式规范。

十、EBCDIC → ASCII Transcoding

Network Program 还要:

1
EBCDIC → ASCII

这一点和 RFC 6 非常值得对照。

RFC 6 讨论的是:

1
2
3
IMP
是否负责
Local Code ↔ ASCII

RFC 7 的具体 UCLA 软件设计却把:

1
EBCDIC → ASCII

放到了:

1
Network Program

里。

也就是:

1
2
3
4
5
6
7
User Data

Host Network Program
↓ EBCDIC → ASCII
Message

IMP

这说明字符转换职责已经出现从网络设备向 Host 软件上移的趋势。

几个月后的 RFC 20 又进一步明确网络交换 ASCII 表示。

十一、Buffer Pool 是 Network Program 和 Handler 的数据交接面

Network Program 不直接把每条消息同步塞进硬件。

它先把完整 Message 放入:

1
pool of buffers

Handler 再从这些 Buffer 中取数据发送。

于是:

1
2
3
4
5
Network Program
↓ fill
Buffer Pool
↓ empty
Handler

两层之间被缓冲区解耦。

十二、Buffer 多大

RFC 7 计算:

1
2
Maximum Text = 1006 bytes
Heading + Marking = 4 bytes

因此完整:

1
1006 + 4 = 1010 bytes

Buffer 至少需要容纳:

1
1010 bytes

文档于是建议:

1
256 words = 1024 bytes

作为一个方便的 Buffer Size。

也就是比最大消息略大一点:

1
2
1010 bytes required
1024 bytes actual buffer

余量:

1
14 bytes

这里体现出一种非常典型的工程做法:

根据协议最大单元,选择一个机器上方便管理的自然 Buffer Size。

RFC 7 还特别指出:

Buffer 的数量会决定 Link 能被利用的频率。

这句话虽然没有展开算法,但非常有意义。

因为当 RFNM 或其他流控机制限制发送时,系统能否预先准备多个不同 Link 的消息,会直接影响硬件利用率。

如果只有一个 Buffer:

1
2
Link A 等待
→ Handler 可能空闲

如果有多个 Buffer:

1
2
3
4
Link A 等待
Link B Ready
Link C Ready
→ Handler 可以继续处理其他工作

这已经是在考虑:

1
2
3
4
5
6
7
Buffering
+
Multiplexing
+
Flow Control
+
Hardware Utilization

之间的关系。

十四、Interface Table 是数据面之外的逻辑信息通道

RFC 7 明确区分:

1
Data

和:

1
Logical Information

Data 通过:

1
Buffer Pool

传递。

Logical Information 通过:

1
Interface Table

传递。

所以两层之间实际上存在:

1
2
3
Data Path
+
Control Metadata Path

十五、Interface Table 采用 Ring Table

RFC 7 建议:

1
ring table

并使用两个指针:

1
2
Filling Pointer
Extracting Pointer

其中:

1
2
Network Program
→ 更新 Filling Pointer
1
2
Handler
→ 更新 Extracting Pointer

每个表项包含类似:

1
2
Buffer Address
Number of Bytes

可以抽象为:

flowchart LR
    NP[Network Program]
    FP[Filling Pointer]
    T1[Buffer Addr + Length]
    T2[Buffer Addr + Length]
    T3[Buffer Addr + Length]
    EP[Extracting Pointer]
    HP[Handler]

    NP --> FP
    FP --> T1
    T1 --> T2
    T2 --> T3
    T3 -.Ring.-> T1
    EP --> HP

从现代视角看,它很像:

1
Ring Buffer Descriptor Queue

或:

1
Producer / Consumer Ring

但不能说今天 NIC Descriptor Ring 直接继承自 RFC 7。

更合理的理解是:

当软件的一层生产 I/O 工作、另一层异步消费时,环形描述符队列是一种非常自然的结构。

关键机制与工作流程

一、一次发送请求的完整路径

把 RFC 7 的内容串起来,一个用户发送 Text 的流程大致是:

sequenceDiagram
    participant U as User Program
    participant N as Network Program
    participant B as Buffer Pool
    participant T as Interface Table
    participant H as Handler
    participant HW as Channel Hardware
    participant I as IMP

    U->>N: text addr + length + destination
    N->>N: 根据 Link 做 Multiplex
    N->>N: 构造 16-bit Heading
    N->>N: 插入 16-bit Marking
    alt text > 1006 bytes
        N->>N: 拆成多个 Message
    end
    N->>N: EBCDIC → ASCII
    N->>B: 填充 Message
    N->>T: 写 Buffer Addr + Length
    N->>T: 移动 Filling Pointer
    H->>T: 读取待发送描述
    H->>B: 取 Message
    H->>HW: 启动发送
    HW->>I: Message
    HW-->>H: I/O Interrupt / Device Status
    H->>T: 更新 Extracting Pointer

从这个流程中能非常清晰地看到三层职责:

1
2
3
4
5
6
7
8
用户层:
“我要发什么,发到哪里”

Network Program:
“怎样把用户语义变成网络 Message”

Handler:
“怎样让硬件真的把 Message 发出去”

二、Network Program 和 Handler 的生产者—消费者关系

可以简化成:

1
2
3
4
5
6
7
8
9
10
11
Network Program
|
| produce
v
+---------------------+
| Buffer + Descriptor |
+---------------------+
|
| consume
v
Handler

其中:

1
2
Network Program:准备工作
Handler:执行 I/O

这避免 Network Program 阻塞在每一个硬件操作上。

三、为什么 Handler 要运行在 Master Mode

RFC 7 说 Handler 运行在:

1
master mode

也就是需要使用特权指令。

原因非常直接。

Handler 要:

  • 控制 channel hardware;
  • 启动发送;
  • 处理中断;
  • 查看设备状态;
  • 做 data chaining。

这些都属于普通用户程序不应该直接拥有的能力。

因此:

1
2
3
4
5
6
7
User Program

Network Program

Privileged Handler

Hardware

本质上已经在强化:

1
Privilege Boundary

四、Output Message Processing Pipeline

RFC 7 的 Network Program 可以重构成下面的 pipeline:

flowchart TD
    A[User Request]
    B[Read Text Address / Length / Destination]
    C[Build 16-bit Host Heading]
    D[Insert 16-bit Marking]
    E{Text > 1006 bytes?}
    F[Split into Messages]
    G[Transcode EBCDIC → ASCII]
    H[Fill Buffer Pool]
    I[Update Interface Table]
    J[Move Filling Pointer]
    K[Handler Ready]

    A --> B --> C --> D --> E
    E -->|Yes| F --> G
    E -->|No| G
    G --> H --> I --> J --> K

今天开发者会把它叫:

1
2
3
4
5
6
Encode
Frame
Fragment
Transform
Queue
Dispatch

这些名字更现代,但结构非常相似。

五、Input 方向为什么没有展开

RFC 7 明确说输入方向和输出方向非常相似,因此主要聚焦 output。

可以合理整理为:

1
2
3
4
5
6
7
8
9
10
11
12
13
IMP

Hardware

Handler

Buffer

Interface Table

Network Program
↓ 根据 Link 分发
User

但要注意:

RFC 7 没有逐项写出完整接收算法。

因此今天重构输入流程时,只能保留:

1
对称的高层结构

不能凭空补:

  • checksum 细节;
  • retry;
  • timeout;
  • exact interrupt sequence。

六、真正困难的问题出现在硬件结束边界

RFC 7 第三章提出:

Handler 怎么知道 incoming message 的真实长度?

一种选择是:

1
提前从前一条信息得知长度

另一种是:

1
2
永远准备最大长度 Buffer
真实消息结束时由硬件触发 Interrupt

这是一个很典型的:

1
Framing / Message Boundary

问题。

数据流里只有 bit 或 byte 并不够。

接收方必须知道:

1
一条 Message 到哪里结束。

七、Padding 与 Message End 绑定

RFC 7 还问:

1
2
3
Outgoing Message End
什么时候通知特殊硬件
以开始 padding?

程序会告诉 MIOP/SIOP:

1
Number of Bytes

最后一个 byte 发完后获得 Interrupt。

作者进一步问:

这个信号是不是也应该送给负责 padding 的特殊设备?

也就是说:

1
2
3
4
Length
End-of-Message
Padding
Interrupt

之间还没有完全敲定。

这正是软件—硬件协同设计的难点。

八、为什么作者质疑 Host-IMP 缺少 Control Procedure

RFC 7 的第一个开放问题是:

1
2
为什么 HOST 与 IMP 之间
没有简单的 Control Procedure?

场景是:

1
2
HOST
→ 本地 IMP

传输时如果已经出错,而 IMP 没有在本地直接解决,错误可能继续穿过网络到:

1
Receiving HOST

那么就会出现:

1
2
本地接口错误
却让远端 Host 来发现

的问题。

于是 Deloche 问:

难道还要依赖 Host-Host Control Procedure 来处理吗?

这是非常重要的分层问题:

1
2
3
4
5
6
Local Link / Interface Error
应该在本地处理?

还是:
End-to-End Host Protocol
统一处理?

九、这里已经出现“局部可靠性”和“端到端可靠性”的张力

可以画成:

flowchart LR
    A[Sending HOST]
    B[Local IMP]
    C[Network]
    D[Remote IMP]
    E[Receiving HOST]

    A --> B --> C --> D --> E

    X[Error on HOST-IMP transmission]
    X -.发生在.-> A
    X -.或.-> B

    Q{谁负责发现和恢复?}
    Q --> L[Local HOST-IMP Control]
    Q --> H[HOST-HOST Control]

RFC 7 没有给最终答案。

但这个问题非常现代:

哪一层应该修复哪一种错误?

十、User-Network Interface 还没定,因为依赖 GORDO

RFC 7 最后一个问题是:

1
什么时候能拿到 Gordo 文档?

因为作者需要知道:

1
2
程序怎样启动
参数怎样在程序之间传递

才能真正设计:

1
2
3
User Program

Network Program

的接口。

后来的 RFC 11 明确说明:

1
2
3
GORDO
=
UCLA Host 的 Operating System

并进一步把:

  • Network Program;
  • Handler;
  • Buffer;
  • Connection;
  • User Transaction;

真正映射到 GORDO 里。

所以 RFC 7 是:

1
Architecture Sketch

RFC 11 则更接近:

1
OS-Specific Implementation Design

重点概念与术语

Host-IMP Interface

Host-IMP Interface(主机—IMP 接口)

它不是单纯一个物理插头。

在 RFC 7 中同时包括:

1
2
3
4
5
6
Host Software
Channel Hardware
Message Format
Buffering
Interrupt
Control

是一整条 Host 接入网络的软硬件边界。

Network Program

面向用户网络请求的软件组件。

主要负责:

  • Multiplex;
  • Distribution;
  • Message Processing;
  • Link 管理相关信息;
  • Header;
  • Marking;
  • Fragmentation;
  • Transcoding;
  • Buffer 管理。

Handler Program

更贴近硬件的特权程序。

负责:

  • channel hardware;
  • emission;
  • data chaining;
  • device status;
  • interrupt;
  • buffer consumption;
  • interface table。

Multiplexing

Multiplexing(多路复用)

多个用户共享同一网络设施。

RFC 7 根据:

1
Link Identification Number

组织多路通信。

Distribution

输入方向的分发。

Network Program 根据逻辑通信标识,把收到的消息交给正确的用户。

现代通常称:

1
demultiplexing

但 RFC 7 使用 distribution

RFC 7 将其描述为两个用户之间的逻辑连接。

后续协议会继续重构 Link 与 Connection 的关系,因此只能按 RFC 7 当前语境理解。

Host Heading

Host 加在消息前面的:

1
16-bit Heading

包含:

1
2
3
4
Trace
Spare
Link ID
Destination Host

Trace

1-bit 追踪标志。

用于网络测量和调试。

Marking

Heading 与 Text 之间的 16-bit 标记。

用于:

1
word alignment

并帮助定位正文起点。

Word Boundary

Word Boundary(机器字边界)

早期大型机的软件和 I/O 高度受机器字结构影响,所以网络 Message 也需要照顾对齐。

EBCDIC

EBCDIC(Extended Binary Coded Decimal Interchange Code)

RFC 7 的 UCLA 软件设计会把待发送的 EBCDIC 字符转成 ASCII。

ASCII

当时逐渐被采用作为网络交换字符表示。

RFC 20 后来明确提出:

1
2
7-bit ASCII
embedded in 8-bit byte

Buffer Pool

Network Program 和 Handler 之间交换 Message 数据的共享缓冲区池。

Interface Table

Network Program 和 Handler 交换逻辑描述信息的数据结构。

表项包含:

1
2
Buffer Address
Number of Bytes

Ring Table

环形表。

使用:

1
2
Filling Pointer
Extracting Pointer

形成生产者—消费者队列。

Filling Pointer

由 Network Program 移动。

指向:

1
下一个应该填入描述信息的位置。

Extracting Pointer

由 Handler 移动。

指向:

1
下一个应该被发送/消费的描述。

Data Chaining

Handler 控制通道设备时可能使用的连续数据传输机制。

原文没有展开具体硬件细节,因此不应把它强行对应到某一种现代 DMA Scatter/Gather 实现。

Master Mode

特权执行模式。

Handler 因为需要控制 I/O 和中断,所以运行在特权环境。

I/O Supervisor

操作系统中负责 I/O 管理的特权组件。

RFC 7 认为 Handler 应集成到这里。

MIOP / SIOP

RFC 7 在硬件问题中提到:

1
MIOP/SIOP

它们属于 Sigma 7 I/O 架构相关术语。

RFC 7 本身没有为现代读者完整定义这两个缩写,因此阅读本文时只需要知道:

作者正在确认专用 Host-IMP Channel Hardware 应挂接在 Sigma 7 的哪种 I/O 处理路径上。

GORDO

UCLA Sigma 7 上的时间共享操作系统。

RFC 11 明确把 GORDO 称为:

1
Operating System of the UCLA HOST

RFC 7 还在等待 GORDO 文档,以设计 User-Network Program Interface。

需要特别注意的点

1. RFC 7 是 Preliminary Design,不是最终规范

原文自己明确定位为初步软件设计,而且整篇以 Questions 收尾。

所以不能把其中:

  • 16-bit Heading;
  • 1006-byte Text;
  • 1024-byte Buffer;
  • EBCDIC → ASCII;

理解成后来整个 ARPANET 永久不变的规范。

2. RFC 100 已经把它标为 Obsolete

1971 年:

1
RFC 7 → Obsolete

因此它今天主要用于:

1
2
3
历史
架构演化
OS 网络软件研究

而不是现行实现。

3. 原始文档是手写稿,当前文本是后期重建

碰到:

1
unreadable

不要自行补成一个“合理句子”。

RFC 7:

1
Link = 两个用户之间的逻辑连接

后来 RFC 11 又进一步区分:

1
2
3
Connection
=
pair of directional Links

再到 RFC 33:

1
2
3
4
Connection
Socket
NCP
Control Command

抽象不断变化。

5. 16-bit Heading 很快也会变化

RFC 7 使用:

1
16-bit Host Heading

后来的 Host-IMP 设计会使用更完整的 Leader 结构。

RFC 11 中已经出现:

1
32-bit leader

所以 RFC 7 只是接口演化中的一个阶段。

6. 8080 bits 是当时的 Host Message 上限,不是互联网永久 MTU

不要类比成:

1
2
3
IP MTU
Ethernet MTU
TCP MSS

这些层次和定义不同。

7. 1006-byte 拆分不是 IP Fragmentation

虽然行为都是:

1
2
大数据
→ 拆成多个单元

但 RFC 7 的拆分发生在:

1
Host Network Program

针对用户 Text 与 Host Message 上限。

它不是后来 IP 层的 Fragmentation。

8. Spare Bit 只是建议,不能当正式“More Fragments”位

RFC 7 只是备注:

可以使用一个 Spare bit 表示多个 Message 属于同一 Text。

不能把它直接写成:

1
RFC 7 定义了 MF bit

更不能和 IPv4 的 MF 建立直接继承关系。

9. EBCDIC → ASCII 并不意味着所有 Host 都统一使用 EBCDIC

这是 UCLA 这个具体设计里的转换。

不同 ARPANET Host 本来就可能使用不同字符表示。

RFC 7 不是在说:

1
所有 ARPANET Host 内部都是 EBCDIC。

10. RFC 6 与 RFC 7 的字符转换职责已经出现变化

RFC 6:

1
讨论 IMP 做转换

RFC 7:

1
UCLA Network Program 做 EBCDIC → ASCII

这说明职责边界正在调整。

不要为了构造“统一架构”把两个 RFC 硬解释成完全一致。

RFC 6:

1
five bit link field

RFC 7:

1
8-bit Link ID

原始早期规范快速变化,才是正确解释。

12. 1024-byte Buffer 不是协议强制要求

RFC 7 的逻辑是:

1
最大完整 Host Message ≈ 1010 bytes

因此:

1
1024-byte Buffer

很方便。

这是实现建议,不是 wire protocol 字段。

13. Ring Table 也只是一种候选实现

原文的语气是:

1
could be a ring table

这不是:

1
所有 Host 必须实现 Ring Buffer。

14. Handler 不等于现代 Linux NIC Driver

二者确实有类似职责:

1
2
3
硬件控制
中断
Buffer

但运行环境、I/O 架构、DMA 机制、协议栈边界都完全不同。

类比只能帮助理解,不应该写成技术继承关系。

15. RFC 7 明确暴露了一个尚未解决的 Error Boundary

作者质疑:

1
2
HOST→IMP transmission error
为什么可能一直传到 receiving HOST 才处理?

这是文档的核心开放问题之一。

它不应该在博客中被“补答案”抹掉。

16. Input Message Length 还是开放问题

RFC 7 没有最终决定:

1
2
Handler
怎样知道真实 incoming Message length

所以不能根据现代经验自行补一个 Length Header。

17. GORDO 不是协议名

GORDO 是 UCLA Host 的操作系统。

RFC 7 提它,是因为:

1
User-Network Interface

必须适配操作系统已有:

  • process;
  • program initiation;
  • parameter passing;

机制。

18. 今天看到的 Fig. 1 / Fig. 2 不是原图的高保真还原

机器可读版使用 ASCII 重建图形。

博客重新用 Mermaid 表达时,应该提取:

1
结构关系

而不是假装恢复原始图纸的精确布局。

从今天的视角重新看这篇 RFC

RFC 7 的具体实现已经没有现实使用价值。

但从软件架构角度看,它非常“现代”。

一、它已经在做 Control Path 与 Data Path 分离

Network Program 与 Handler 之间:

1
2
Message Data
→ Buffer Pool

而:

1
2
3
4
Buffer Address
Length
Logical State
→ Interface Table

也就是:

1
2
3
4
Data

Metadata
分开传递

现代系统里非常常见:

1
2
3
Payload Buffer
+
Descriptor

二、它本质上是 Producer-Consumer

RFC 7 的:

1
2
3
4
5
Network Program
→ Filling Pointer

Handler
→ Extracting Pointer

就是一个生产者—消费者模型。

抽象后:

flowchart LR
    P[Producer<br/>Network Program]
    Q[Ring / Queue]
    C[Consumer<br/>Handler]

    P -->|Fill| Q
    Q -->|Extract| C

这类模型今天存在于:

  • NIC TX/RX Ring;
  • Disruptor;
  • Message Queue;
  • IO Completion Queue;
  • Kernel Driver Descriptor Queue;
  • Streaming Pipeline。

三、Buffering 是解耦不同速度组件的基础

Network Program 产生 Message 的速度:

1
不一定等于

Channel Hardware 发送速度。

所以 Buffer Pool 提供:

1
Elasticity

如果没有 Buffer:

1
上层每次都必须等硬件完成

有 Buffer 后:

1
2
上层准备下一项工作
底层异步发送当前项

这就是异步 I/O 最基本的思想之一。

四、Ring 结构的价值在于固定内存和低成本循环复用

环形表天然适合:

1
2
固定数量 Descriptor
反复使用

而不需要:

1
每条 Message 动态创建 / 删除队列节点

这也是为什么类似 Ring 的结构在高性能 I/O 中至今常见。

再次强调:

这是结构上的自然相似,不是“现代 NIC Ring 起源于 RFC 7”的历史结论。

五、协议代码与设备驱动应该解耦

RFC 7 把:

1
Network Program

和:

1
Handler

分开,很有现实意义。

如果以后 Channel Hardware 变化:

1
理论上主要替换 Handler / Hardware Interface

而用户和较高层网络逻辑可以少改。

现代分层也是类似目标:

1
2
3
4
5
6
7
Application

Socket / Protocol

Driver

NIC

六、用户程序应该传语义,不应该传硬件命令

RFC 7 设想用户只给:

1
2
3
address
length
destination

而不是:

1
2
3
启动哪个 I/O channel
设置哪个设备寄存器
什么时候产生 interrupt

这就是一个非常关键的系统软件原则:

上层描述“我要什么”,底层决定“硬件怎样做”。

七、Fragmentation 的边界选择一直是系统设计问题

RFC 7 选择:

1
Network Program

把大 Text 拆成 Message。

现代系统仍然要问:

1
2
3
4
5
应用分块?
RPC 层分帧?
Transport 分段?
IP 分片?
存储层 chunk?

不同层做 fragmentation,会带来不同:

  • 重组成本;
  • 错误恢复范围;
  • 内存压力;
  • 延迟;
  • 重试粒度。

RFC 7 虽然很早,但已经实际面对这个问题。

八、Alignment 不是历史遗迹,高性能系统今天仍然在意

RFC 7 插入 Marking 是为了:

1
word boundary

今天我们依然在考虑:

1
2
3
4
5
cache-line alignment
SIMD alignment
DMA alignment
page alignment
memory-mapped I/O alignment

只是硬件背景变化了。

九、不要让本地接口错误无脑传播成远端错误

RFC 7 的开放问题非常值得今天微服务系统借鉴。

假设:

1
2
3
4
5
Service A
→ Local Proxy
→ Network
→ Remote Proxy
→ Service B

如果:

1
A→Local Proxy

内部格式就已经出错,却一直让 B 来发现,故障定位会非常困难。

所以现代系统会尽量在最近边界进行:

1
validation

但同时又保留:

1
end-to-end validation

这就是:

1
2
3
local check
+
end-to-end check

的组合。

十、用户 API 设计取决于操作系统进程模型

RFC 7 无法完成 User-Network Interface,是因为还需要 GORDO 的:

1
2
process initiation
parameter passing

信息。

这是非常真实的系统设计约束。

API 从来不是悬空的。

它必须嵌入:

1
2
3
4
5
6
线程模型
进程模型
内存模型
权限模型
调度模型
I/O 模型

今天设计:

  • io_uring;
  • async/await;
  • Java NIO;
  • virtual threads;
  • Netty EventLoop;

也仍然受运行时模型约束。

十一、从 RFC 7 到 RFC 11,可以看到“架构设计 → 平台落地”

RFC 7:

1
2
3
4
5
Network Program
Handler
Buffers
Interface Table
Questions

RFC 11:

1
2
把这些概念
真正集成进 GORDO

并详细讨论:

  • allocation tables;
  • buffer pages;
  • Handler;
  • Network;
  • system calls;
  • process;
  • connections。

这是一个非常典型的软件工程过程:

1
2
3
4
5
Architecture

Platform Constraints

Concrete Implementation

十二、现代“网络栈分层”不是一开始就存在的

RFC 7 最大的历史价值之一,是让我们看到这些边界正在被创造。

今天教材画:

1
2
3
4
5
Application
Transport
Network
Link
Physical

看起来很自然。

但 1969 年真实的问题是:

1
2
3
4
5
6
7
8
9
字符转换谁做?
Header 谁加?
Message 谁切?
Buffer 谁维护?
硬件谁启动?
错误谁处理?
Length 谁知道?
Control Procedure 放哪?
User API 长什么样?

这些争论经过多年才形成更稳定的分层。

这篇 RFC 带来的影响

RFC 7 本身没有成为长期标准。

1971 年它已经被归入:

1
Obsolete

但它在早期 ARPANET 软件演化中有几个非常明确的位置。

一、它把 Host-IMP Interface 从“概念讨论”推进到“软件模块设计”

RFC 6 更像:

1
我们需要哪些控制能力?

RFC 7 则是:

1
2
3
我们准备写两个程序
它们通过什么数据结构通信
每一步具体做什么

也就是从:

1
Protocol Discussion

进入:

1
Software Architecture

二、它是 RFC 11 的明显前身

RFC 11 的标题:

Implementation of the Host-Host Software Procedures in GORDO

其中明确写:

1
2
3
GORDO
=
Operating System of the UCLA HOST

并继续使用:

1
2
3
Network Program
Handler
Buffers

这些 RFC 7 已经出现的概念。

可以把两篇关系粗略理解成:

flowchart LR
    A[RFC 7<br/>Host-IMP Interface<br/>Preliminary Design]
    B[RFC 11<br/>Host-Host Procedures<br/>Implementation in GORDO]

    A --> B

这不是正式的 RFC Updates/Obsoletes 元数据关系,而是内容上的设计延续。

三、字符转换逐渐从 IMP 讨论转向 Host / Host-Host 约定

演化可以大致看成:

1
2
3
4
5
6
7
8
9
10
11
RFC 6
→ 讨论 IMP 做 local code ↔ ASCII

RFC 7
→ UCLA Network Program 做 EBCDIC → ASCII

RFC 20
→ 约定 Network Interchange 使用 7-bit ASCII in 8-bit byte

RFC 33
→ 明确避免对 character set / programming language 施加不必要限制

这条线非常值得读。

它体现了网络架构逐渐从:

1
“网络替应用理解数据”

转向:

1
2
“网络提供通用通信能力,
表示语义由更上层协议处理”

四、它提前暴露了 Host-IMP Error Handling 的分层问题

RFC 7 问:

1
2
本地 HOST→IMP 错误
为什么要让远端 Host 才处理?

后续网络协议会持续围绕:

  • Host-IMP protocol;
  • Host-Host protocol;
  • error control;
  • status testing;
  • RFNM;
  • checksum;

进行讨论。

这说明:

错误恢复层次从 ARPANET 最早期就不是一个简单问题。

五、它保存了操作系统网络子系统成形之前的架构痕迹

RFC 7 已经出现:

1
2
3
4
5
6
7
8
User Interface
Network Program
Handler
Buffer Pool
Interface Table
Interrupt
Privileged Mode
Hardware Interface

如果把这些名词全部替换成现代词汇,会显得非常熟悉。

但真正重要的是:

1969 年的人们已经意识到,网络不能只是一个应用程序,它必须成为操作系统的一项共享基础能力。

六、它也展示了“实现文档”的价值

很多 RFC 关注:

1
协议线上格式

RFC 7 却大量讨论:

1
2
3
4
5
6
Buffer
Pointer
Program
Interrupt
Hardware
Operating System

这提醒我们:

协议能不能成功,往往不只取决于规范好不好,还取决于它是否能自然嵌入真实操作系统。

七、RFC 33 后来会把 Host 侧抽象提升为 NCP

1970 年的 RFC 33 已经使用:

Network Control Program(NCP)

它负责:

1
2
3
4
establish connections
break connections
switch connections
control flow

并通过:

1
system calls

为 Host 进程提供网络能力。

这比 RFC 7 的:

1
2
3
Network Program
+
Handler

抽象更成熟。

可以粗略画成:

flowchart LR
    A[RFC 7<br/>Network Program + Handler]
    B[RFC 11<br/>GORDO Implementation]
    C[RFC 33<br/>NCP + Connection + Socket]
    D[ARPANET NCP / Host-Host Protocol]

    A --> B --> C --> D

这不是严格版本升级链,但很好地展示了:

1
Host 网络软件

如何逐渐形成更清晰的系统抽象。

八、它最值得今天软件开发者继承的是“边界与队列”思维

RFC 7 中两个最持久的工程思想可以压缩为:

1. 明确边界

1
2
3
4
5
User
↔ Network Software
↔ Privileged Handler
↔ Hardware
↔ Network

每层都应该有清晰职责。

2. 用队列解耦

1
2
3
Producer
→ Buffer / Descriptor
→ Consumer

不要让上层逻辑和硬件执行速度完全绑定。

这两点直到今天仍然存在于几乎所有高性能 I/O 系统里。

总结

RFC 7 是一篇非常“软件工程”的早期 RFC。

它不再只问:

1
Host 应该怎样通信?

而开始问:

1
2
这些通信能力
在操作系统里到底写成什么程序?

答案是两个主要组件:

1
2
3
Network Program
+
Handler Program

Network Program 面向用户和网络语义:

1
2
3
4
5
6
7
8
9
Multiplex
Distribution
Header
Marking
Length Check
Fragmentation
EBCDIC → ASCII
Buffer Fill
Interface Table

Handler 面向硬件:

1
2
3
4
5
6
7
Channel Control
Emission
Data Chaining
Interrupt
Device Status
Buffer Drain
Interface Table

两者通过:

1
2
3
Buffer Pool
+
Interface Table

解耦。

Interface Table 又使用一个非常经典的结构:

1
2
3
4
5
Ring Table
+
Filling Pointer
+
Extracting Pointer

一条发送请求从用户进入系统以后,大致经历:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
User Program

text location
text length
destination

Network Program

16-bit Heading
16-bit Marking

超过 1006 bytes?

拆分 Message

EBCDIC → ASCII

Buffer Pool

Interface Table

Handler

Channel Hardware

IMP

RFC 7 还给出了一个非常具体的 16-bit Heading:

1
2
3
4
Trace        1 bit
Spare 2 bits
Link ID 8 bits
Destination 5 bits

由于:

1
2
3
Max Host Message = 8080 bits
Heading = 16 bits
Marking = 16 bits

所以最大 Text:

1
2
(8080 - 32) / 8
= 1006 bytes

再加上 Heading 和 Marking:

1
2
1006 + 4
= 1010 bytes

因此实现建议使用:

1
1024-byte Buffer

这些数字今天已经没有协议实现价值。

RFC 7 在 1971 年就被标记为:

1
Obsolete

但它留下了几个非常值得学习的问题:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
用户语义和设备控制应该怎样分层?

多用户怎样共享一个物理网络接口?

软件层和驱动层怎样通过 Buffer 解耦?

数据和描述信息是否应该分开?

怎样设计生产者—消费者队列?

大消息在哪一层切分?

字符表示转换在哪一层完成?

本地接口错误应该本地处理,
还是交给端到端协议?

接收端怎样知道 Message Boundary?

用户 API 怎样适配操作系统的进程模型?

最值得注意的是,RFC 7 没有假装这些问题已经全部解决。

它最后直接留下:

1
Questions

因为当时:

  • Host-IMP Control Procedure 还没定;
  • Message End 的硬件信号还没定;
  • Incoming Length 处理还没定;
  • GORDO 用户接口也还没定。

这让 RFC 7 看起来不像今天的最终规范。

但正因为如此,它反而非常适合学习架构设计。

我们看到的不是:

1
一个已经成功的网络栈

而是:

一群工程师正在把“网络通信”这个抽象,一层一层翻译成用户调用、程序模块、Ring Table、Buffer、Interrupt 和硬件命令。

从 RFC 1 到 RFC 7,ARPANET 的 Host Software 正在发生一个非常明显的变化:

1
2
3
4
5
6
7
概念

协议

软件架构

操作系统实现

互联网并不是先有一套完美分层模型,然后大家照着实现。

真实顺序更接近:

1
2
3
4
5
6
7
8
9
10
11
12
13
先让两个程序能说话。

再决定谁负责什么。

再加 Buffer。

再加 Handler。

再处理 Interrupt。

然后发现还有问题。

再写下一篇 RFC。

RFC 7,就是这个过程里非常清晰的一张架构草图。


RFC 7 带读:Host-IMP Interface——从用户请求到硬件中断,ARPANET 主机网络栈的早期分层
https://allendericdalexander.github.io/2026/08/16/rfc/rfc00007-host-imp-interface/
作者
AtLuoFu
发布于
2026年8月16日
许可协议