17 端口和端口驱动程序
如何在 互操作性教程 中使用端口和端口驱动程序的示例。有关提到的 BIF 的信息,请参见 ERTS 中的 erlang(3) 手册页。
17.1 端口
从 Erlang 的角度来看,端口提供了与外部世界通信的基本机制。它们为外部程序提供了一个面向字节的接口。创建端口后,Erlang 可以通过发送和接收字节列表(包括二进制)与之通信。
创建端口的 Erlang 进程被称为端口所有者或端口的连接进程。所有与端口的通信都必须通过端口所有者进行。如果端口所有者终止,端口也会终止(以及外部程序,如果它编写正确)。
外部程序驻留在另一个操作系统进程中。默认情况下,它从标准输入(文件描述符 0)读取并写入标准输出(文件描述符 1)。外部程序在端口关闭时终止。
17.2 端口驱动程序
可以根据某些原则用 C 编写一个驱动程序,并将其动态链接到 Erlang 运行时系统。链接的驱动程序从 Erlang 编程人员的角度来看就像一个端口,被称为端口驱动程序。
错误的端口驱动程序会导致整个 Erlang 运行时系统发生内存泄漏、挂起或崩溃。
有关端口驱动程序的信息,请参见 ERTS 中的 erl_driver(4) 手册页、ERTS 中的 driver_entry(1) 手册页和 Kernel 中的 erl_ddll(3) 手册页。
17.3 端口 BIF
创建端口
open_port(PortName, PortSettings | 打开新 Erlang 端口的结果,返回一个端口标识符 Port。就像 pid 一样,可以向端口标识符发送消息并从中接收消息。端口标识符也可以使用 link/1 链接,或使用 register/2 注册到一个名称下。 |
PortName 通常是一个元组 {spawn,Command},其中字符串 Command 是外部程序的名称。外部程序在 Erlang 工作空间之外运行,除非找到一个名为 Command 的端口驱动程序。如果找到 Command,则启动该驱动程序。
PortSettings 是端口设置(选项)的列表。该列表通常至少包含一个元组 {packet,N},它指定在端口和外部程序之间发送的数据前面都有一个 N 字节的长度指示符。N 的有效值为 1、2 或 4。如果要使用二进制而不是字节列表,则必须包含选项 binary。
端口所有者 Pid 可以通过发送和接收消息来与端口 Port 通信。(实际上,任何进程都可以向端口发送消息,但必须在消息中标识端口所有者)。
发送到端口的消息是异步传递的。
在 Erlang/OTP 16 之前,发送到端口的消息是同步传递的。
在下表中,Data 必须是 I/O 列表。I/O 列表是一个二进制或一个(可能很深)的二进制或整数列表,范围为 0..255
消息 | 描述 |
{Pid,{command,Data}} | 将 Data 发送到端口。 |
{Pid,close} | 关闭端口。除非端口已关闭,否则端口在所有缓冲区刷新并端口真正关闭时,将使用 {Port,closed} 进行回复。 |
{Pid,{connect,NewPid}} | 将 Port 的端口所有者设置为 NewPid。除非端口已关闭,否则端口将使用 {Port,connected} 向旧端口所有者进行回复。请注意,旧端口所有者仍然与端口链接,但新端口所有者没有。 |
消息 | 描述 |
{Port,{data,Data}} | 从外部程序接收 Data。 |
{Port,closed} | 对 Port ! {Pid,close} 的回复。 |
{Port,connected} | 对 Port ! {Pid,{connect,NewPid}} 的回复。 |
{'EXIT',Port,Reason} | 如果端口由于某种原因终止。 |
除了发送和接收消息之外,还可以使用许多 BIF
端口 BIF | 描述 |
port_command(Port,Data) | 将 Data 发送到端口。 |
port_close(Port) | 关闭端口。 |
port_connect(Port,NewPid) | 将 Port 的端口所有者设置为 NewPid。旧端口所有者 Pid 仍然与端口链接,如果不需要,则必须调用 unlink(Port)。 |
erlang:port_info(Port,Item) | 返回由 Item 指定的信息。 |
erlang:ports() | 返回当前节点上的所有端口列表。 |
一些适用于端口驱动程序的其他 BIF:port_control/3 和 erlang:port_call/3。