> For the complete documentation index, see [llms.txt](https://book.bsdcn.org/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://book.bsdcn.org/4.3-bsd-unix-cao-zuo-xi-tong-she-ji-yu-shi-xian/di-si-bu-fen-jin-cheng-jian-tong-xin/11.3.-xie-yi-xie-yi-jie-kou.md).

# 11.3 协议-协议接口

协议模块之间的接口使用 `pr_usrreq()`、`pr_input()`、`pr_output()`、`pr_ctlinput()` 和 `pr_ctloutput()` 例程。`pr_usrreq()` 和 `pr_ctloutput()` 供套接字层与协议通信，调用约定是标准的；其余例程通常不在协议族之外访问，因而演化出各异的调用约定。

理论上为协议的所有入口点强加标准调用约定或许能允许协议模块任意互联，实践上却非常困难：跨越协议族边界需要把网络地址从调用方域的格式转换成被调方域的格式。因此，不同通信域之间协议的连接一般不受支持，前段所列例程的调用约定通常按域标准化。

下面几小节简述协议的一般框架和调用约定。第 12 章考察具体协议如何嵌入这一框架。

**pr\_output**

协议输出例程常用为在一条连接上发送单条消息而设计的调用约定，例如：

```c
error = (*pr_output)(pcb, m);
    struct pcb *pcb;
    struct mbuf *m;
```

较低层协议的输出例程不一定总有协议控制块，可能需要更显式的参数。

**pr\_input**

上层协议的输入例程通常在网络层协议找到协议标识符之后于软件中断级被调用。它们一般比输出例程更程式化，因为常经协议开关调用。视协议族性质，它们可能收到标识连接的控制块指针，也可能得从收到分组的信息中定位控制块。典型的调用约定是：

```c
(void) (*pr_input)(m, ifp);
    struct mbuf *m;
    struct ifnet *ifp;
```

本例中，收到分组的接口作为第二参数传递，由协议做连接级的多路分解。

**pr\_ctlinput**

这一例程用来把 **控制** 信息（可能传给用户、但不属于数据的信息）从一个协议模块向 **上** 传给另一个。常用调用约定是：

```c
(void) (*pr_ctlinput)(req, addr);
    int req;
    struct sockaddr *addr;
```

`req` 参数取表 11.4 所列值之一，`addr` 参数是条件适用的地址。许多请求源自网际控制报文协议（ICMP）\[Postel, 1981] 和 1822 主机/IMP 约定中定义的错误报文 \[BBN, 1978]。

表 11.4 控制输入例程的请求

| 请求                     | 描述             |
| ---------------------- | -------------- |
| PRC\_IFDOWN            | 网络接口变迁         |
| PRC\_ROUTEDEAD         | 尽可能另选路由        |
| PRC\_MSGSIZE           | 消息大小迫使分组被丢弃    |
| PRC\_HOSTDEAD          | 远程主机关机         |
| PRC\_HOSTUNREACH       | 远程主机不可达        |
| PRC\_UNREACH\_NET      | 无到网络的路由        |
| PRC\_UNREACH\_HOST     | 无到主机的路由        |
| PRC\_UNREACH\_PROTOCOL | 目的地不支持该协议      |
| PRC\_UNREACH\_PORT     | 目的地端口号未使用      |
| PRC\_UNREACH\_NEEDFRAG | 需要分片但不允许       |
| PRC\_UNREACH\_SRCFAIL  | 源路由失败          |
| PRC\_REDIRECT\_NET     | 网络的路由重定向       |
| PRC\_REDIRECT\_HOST    | 主机的路由重定向       |
| PRC\_REDIRECT\_TOSNET  | 按服务类型与网络的路由重定向 |
| PRC\_REDIRECT\_TOSHOST | 按服务类型与主机的路由重定向 |
| PRC\_TIMXCEED\_INTRANS | 分组寿命在传输中耗尽     |
| PRC\_TIMXCEED\_REASS   | 寿命在重组队列中耗尽     |
| PRC\_PARAMPROB         | 检测到头部参数问题      |


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://book.bsdcn.org/4.3-bsd-unix-cao-zuo-xi-tong-she-ji-yu-shi-xian/di-si-bu-fen-jin-cheng-jian-tong-xin/11.3.-xie-yi-xie-yi-jie-kou.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
