查看源代码 端口和端口驱动程序
关于如何使用端口和端口驱动程序的示例,请参阅互操作性教程。有关提到的 BIF 的信息,请参阅 ERTS 中的模块 erlang
。
端口
从 Erlang 的角度来看,端口提供了与外部世界通信的基本机制。它们为外部程序提供了一个面向字节的接口。创建端口后,Erlang 可以通过发送和接收字节列表(包括二进制数据)与之通信。
创建端口的 Erlang 进程被称为端口的端口所有者,或端口的连接进程。所有与端口的通信都必须通过端口所有者。如果端口所有者终止,则端口也会终止(如果外部程序编写正确,则外部程序也会终止)。
外部程序驻留在另一个操作系统进程中。默认情况下,它从标准输入(文件描述符 0)读取,并写入标准输出(文件描述符 1)。当端口关闭时,外部程序应该终止。
端口驱动程序
可以根据某些原则用 C 语言编写驱动程序,并将其动态链接到 Erlang 运行时系统。从 Erlang 程序员的角度来看,链接的驱动程序看起来像一个端口,被称为端口驱动程序。
警告
错误的端口驱动程序会导致整个 Erlang 运行时系统内存泄漏、挂起或崩溃。
有关端口驱动程序的信息,请参阅
- erl_driver 在 ERTS 中
- driver_entry 在 ERTS 中
erl_ddll
在 Kernel 中
端口 BIF
要创建一个端口,请调用 open_port(PortName, PortSettings)
。它返回一个端口标识符 Port
,作为打开新端口的结果。消息可以像 PID 一样发送和接收到端口标识符。端口标识符也可以使用 link/1
链接,或使用 register/2
在名称下注册。
PortName
通常是一个元组 {spawn,Command}
,其中字符串 Command
是外部程序的名称。除非找到名称为 Command
的端口驱动程序,否则外部程序在 Erlang 工作区之外运行。如果找到 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 可以使用
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