IV. NCP
我们认为 NCP 由五个组成程序、三张关联表、若干队列和缓冲区以及一张链路分配表构成。当然, 每个站点都会改动这一设计以满足自己的需要, 因此我们的设计仅作示例。
组成程序
1. 输入处理程序
这是一个中断驱动的输入例程。它启动 Imp-to-Host 传输, 把数据传入一个常驻缓冲区, 并在传输完成时唤醒输入解释程序。
2. 输出处理程序
这是一个中断驱动的输出例程。它启动 Host-to-Imp 传输, 把数据从一个常驻缓冲区传出, 并在传输完成时唤醒输出调度程序。
3. 输入解释程序
该程序判定输入是发给用户的常规消息、控制消息、Imp-to-Host 消息, 还是一个错误。对于每一类消息, 该程序都会采取相应的动作。
4. 输出调度程序
发往 Imp 的消息有三类
-
Host-to-Imp 消息
-
控制消息
-
常规消息
我们认为应当在这几类消息之间规定优先级。我们建议的优先级就是上面的顺序。输出调度程序选出优先级最高的消息并把它交给输出处理程序。
5. 系统调用解释程序
该程序解释来自用户的请求。
其中值得关注的两个组成部分是输入解释程序和系统调用解释程序。二者的相似之处在于, 输入解释程序为外部请求提供服务, 而系统调用解释程序为本地请求提供服务。
关联表
我们设想 NCP 数据库的大部分位于三张关联表中。所谓 "关联", 是指存在某个查找例程, 给它一个键, 它要么成功返回一个指向相应表项的指针, 要么在没有与该键对应的表项时失败。
1. 会合表
"连接请求" 以及连接的其他属性都保存在这张表中。这张表按本地 socket 访问, 但其他表中有指向现有表项的指针。
表项的组成部分有:
-
本地 socket (键)
-
外部 socket
-
链路
-
呼叫方队列
-
文本队列
-
连接状态
-
流量状态
-
指向所连接端口的指针
当用户执行 Init 或 Listen 系统调用时, 或者收到一条 <RFC> 时, 就会创建一个表项。有些字段在连接建立之前不会被使用, 例如, 如果用户执行的是 Listen, 那么在 <RFC> 到达之前外部 socket 是未知的。
2. 输入链路表
输入解释程序以外部主机和链路作为键, 获取一个指针, 指向会合表中使用该传入链路的那条连接的表项。
3. 输出链路表
为了解释 RFNM, 输入解释程序需要一张与输入链路表形式相同、但使用传出链路的表。
链路分配表
这是一个非常简单的结构, 记录每台主机正在使用哪些链路。每台主机用一个字大概就够了。
下图是我们对网络控制程序的构想。方框表示表和缓冲区, 带斜角和双层底的方框表示队列, 锯齿边的方框表示组成程序, 箭头表示数据通路。
各缩写名称的含义如下。
-
ILT: 输入链路表
-
OLT: 输出链路表
-
LAT: 链路分配表
-
RT: 会合表
-
HIQ: 主机到 Imp 队列
-
OCCQ: 输出控制命令队列
-
ORMQ: 输出常规消息队列
-
IHBuf: 由输入处理程序从 IMP 填入、由输入解释程序清空的缓冲区
-
OHBuf: 由输出调度程序从各队列填入、由输出处理程序清空的传出消息缓冲区。
+---------+
| I M P |
+---------+
v ^
| |
+---------------------------|-----|------------------------------+
| | | |
| /\/\/\/\/\/\/\ | | /\/\/\/\/\/\/\ |
| \ / <--------+ +---< \ / |
| / Input \ / Output \ |
| \ Handler / \ Handler / <----+ |
| / \ >------+ / \ | |
| \/\/\/\/\/\/\/ | \/\/\/\/\/\/\/ ^ |
| v +-----+ |
| +-----+ | OH | |
| | IM | | Buf | |
| | Buf | +-----+ |
| +-----+ /\/\/\/\/\/\/\/\ ^ |
| /\/\/\/\/\/\/\/\ v +----> \ / | |
| \ / | | / Output \ >--+ |
| / \ <------+ ^ \ / |
| \ Input / /-----\ / Scheduler \ |
| / \ >-------->| HIQ | \ / |
| \ Interpreter / |_____| / \ |
| / \ >----+ \_____/ \/\/\/\/\/\/\/\/ |
| \/\/\/\/\/\/\/\/ | ^ v ^ |
| ^ ^ ^ \ | /-----\ | | | /-----\ |
| | \ \ \ | | O | | | | | O | |
| | \ \ \ +--->| C |>----+ | +---<| R | |
| v v v \ | C | | | M | |
| +---+ +---+ +---+ \ | Q | v | Q | |
| | | | | | | \ |_____| +---------+ |_____| |
| |ILT| |LAT| |OLT| \ \_____/ | | \_____/ |
| | | | | | | \ ^ | R T | ^ |
| +---+ +---+ +---+ +------|-------->| | | |
| v | +---------+ | |
| | ^ ^ | |
| | /\/\/\/\/\/\/\/\ | | |
| | \ / | | |
| +----------->/ System \<-------+ | |
| \ Call / | |
| / Interpreter \>--------------------+ |
| \ / |
| +-->/ \>--+ |
| | \/\/\/\/\/\/\/\/ | |
+------------------|----------------------|----------------------+
| |
+---< system calls <---+
注: 这份 RFC 由 Donald Eastlake 和 Jill Eastlake 于 1999 年转成机器可读形式, 以便录入在线 RFC 档案馆。
[编者注: 原手绘图用圆柱体表示队列, 用 "软塌塌的、像变形虫一样的东西" 表示组成程序。]