注:机翻,未校。
如有内容异常,请看原文。
Serial Programming Guide for POSIX Operating Systems
POSIX 操作系统串行编程指南
5th Edition, 6th Revision
Copyright 1994-2005 by Michael R. Sweet
Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.2 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A copy of the license is included in Appendix C, GNU Free Documentation License.
允许根据自由软件基金会发布的 GNU 自由文档许可证第 1.2 版或任何后续版本的条款,复制、分发和/或修改本文档;无不变节、无封面文字和无封底文字。许可证副本包含在附录 C,GNU 自由文档许可证中。
Introduction
引言
The Serial Programming Guide for POSIX Operating Systems will teach you how to successfully, efficiently, and portably program the serial ports on your UNIX® workstation or PC.
《POSIX 操作系统的串行编程指南》将教您如何成功、高效且可移植地为您的 UNIX® 工作站或个人电脑编程串行端口。
Each chapter provides programming examples that use the POSIX (Portable Standard for UNIX) terminal control functions and should work with very few modifications under IRIX®, HP-UX, SunOS®, Solaris®, Digital UNIX®, Linux®, and most other UNIX operating systems.
每一章都提供了使用 POSIX(UNIX 的可移植标准)终端控制功能的编程示例,这些示例在 IRIX®、HP-UX、SunOS®、Solaris®、Digital UNIX®、Linux® 和大多数其他 UNIX 操作系统下只需极少修改即可运行。
The biggest difference between operating systems that you will find is the filenames used for serial port device and lock files.
您会发现操作系统之间最大的区别是用于串行端口设备和锁定文件的文件名。
License
许可证
Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.2 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.
允许根据自由软件基金会发布的 GNU 自由文档许可证第 1.2 版或任何后续版本的条款,复制、分发和/或修改本文档;无不变节、无封面文字和无封底文字。
A copy of the license is included in Appendix C, GNU Free Documentation License.
许可证副本包含在附录 C,GNU 自由文档许可证中。
Organization
组织结构
This guide is organized into the following chapters and appendices:
本指南分为以下章节和附录:
-
Chapter 1, Basics of Serial Programming
第 1 章,串行编程基础 -
Chapter 2, Configuring the Serial Port
第 2 章,配置串行端口 -
Chapter 3, Talking to MODEMs
第 3 章,与调制解调器通信 -
Chapter 4, Advanced Serial Programming
第 4 章,高级串行编程 -
Appendix A, RS-232 Pinouts
附录 A,RS-232 引脚布局 -
Appendix B, ASCII Control Codes
附录 B,ASCII 控制码 -
Appendix C, GNU Free Documentation License
附录 C,GNU 自由文档许可证 -
Appendix D, Change History
附录 D,变更历史
Chapter 1, Basics of Serial Communications
第 1 章,串行通信基础
This chapter introduces serial communications, RS-232 and other standards that are used on most computers as well as how to access a serial port from a C program.
本章介绍了串行通信、RS-232 以及其他在大多数计算机上使用的标准,以及如何从 C 程序中访问串行端口。
What Are Serial Communications?
什么是串行通信?
Computers transfer information (data) one or more bits at a time. Serial refers to the transfer of data one bit at a time.
计算机一次传输一个或多个比特的信息(数据)。串行是指一次传输一个比特的数据。
Serial communications include most network devices, keyboards, mice, MODEMs, and terminals.
串行通信包括大多数网络设备、键盘、鼠标、调制解调器和终端。
When doing serial communications each word (i.e. byte or character) of data you send or receive is sent one bit at a time.
在进行串行通信时,您发送或接收的每个字(即字节或字符)的数据是一次发送一个比特。
Each bit is either on or off. The terms you’ll hear sometimes are mark for the on state and space for the off state.
每个比特要么是“开”,要么是“关”。您有时会听到的术语是“标记”表示“开”状态,而“空格”表示“关”状态。
The speed of the serial data is most often expressed as bits-per-second (“bps”) or baudot rate (“baud”).
串行数据的速度通常以每秒比特数(“bps”)或波特率(“baud”)表示。
This just represents the number of ones and zeroes that can be sent in one second.
这仅仅表示在一秒钟内可以发送的 1 和 0 的数量。
Back at the dawn of the computer age, 300 baud was considered fast, but today computers can handle RS-232 speeds as high as 430,800 baud!
在计算机时代的黎明,300 波特被认为是快速的,但如今计算机可以处理高达 430,800 波特的 RS-232 速度!
When the baud rate exceeds 1,000, you’ll usually see the rate shown in kilo baud, or kbps (e.g. 9.6k, 19.2k, etc).
当波特率超过 1,000 时,通常会以千波特(或 kbps)表示速率(例如 9.6k、19.2k 等)。
For rates above 1,000,000 that rate is shown in mega baud, or Mbps (e.g. 1.5Mbps).
对于超过 1,000,000 的速率,以兆波特(或 Mbps)表示(例如 1.5Mbps)。
When referring to serial devices or ports, they are either labeled as Data Communications Equipment (“DCE”) or Data Terminal Equipment (“DTE”).
在提到串行设备或端口时,它们被标记为“数据通信设备”(“DCE”)或“数据终端设备”(“DTE”)。
The difference between these is simple - every signal pair, like transmit and receive, is swapped.
它们之间的区别很简单——每对信号(如发送和接收)都被交换了。
When connecting two DTE or two DCE interfaces together, a serial null-MODEM cable or adapter is used that swaps the signal pairs.
当连接两个 DTE 或两个 DCE 接口时,使用一个串行“空调制解调器”电缆或适配器来交换信号对。
What Is RS-232?
什么是 RS-232?
RS-232 is a standard electrical interface for serial communications defined by the Electronic Industries Association (“EIA”).
RS-232 是由电子工业协会(“EIA”)定义的串行通信的标准电气接口。
RS-232 actually comes in 3 different flavors (A, B, and C) with each one defining a different voltage range for the on and off levels.
RS-232 实际上有 3 种不同的版本(A、B 和 C),每种版本定义了“开”和“关”电平的不同电压范围。
The most commonly used variety is RS-232C, which defines a mark (on) bit as a voltage between -3V and -12V and a space (off) bit as a voltage between +3V and +12V.
最常用的是 RS-232C,它将标记(开)比特定义为 -3V 到 -12V 之间的电压,将空格(关)比特定义为 +3V 到 +12V 之间的电压。
The RS-232C specification says these signals can go about 25 feet (8m) before they become unusable.
RS-232C 规范指出,这些信号可以在变得无法使用之前传输约 25 英尺(8 米)。
You can usually send signals a bit farther than this as long as the baud is low enough.
只要波特率足够低,通常可以将信号传输得比这更远。
Besides wires for incoming and outgoing data, there are others that provide timing, status, and handshaking:
除了用于接收和发送数据的线路外,还有其他线路用于提供定时、状态和握手信号:
Pin | Description | Pin | Description | Pin | Description | Pin | Description | Pin | Description |
---|---|---|---|---|---|---|---|---|---|
1 | Earth Ground | 6 | DSR - Data Set Ready | 11 | Unassigned | 16 | Secondary RXD | 21 | Signal Quality Detect |
2 | TXD - Transmitted Data | 7 | GND - Logic Ground | 12 | Secondary DCD | 17 | Receiver Clock | 22 | Ring Detect |
3 | RXD - Received Data | 8 | DCD - Data Carrier Detect | 13 | Secondary CTS | 18 | Unassigned | 23 | Data Rate Select |
4 | RTS - Request To Send | 9 | Reserved | 14 | Secondary TXD | 19 | Secondary RTS | 24 | Transmit Clock |
5 | CTS - Clear To Send | 10 | Reserved | 15 | Transmit Clock | 20 | DTR - Data Terminal Ready | 25 | Unassigned |
表 1 - RS-232 引脚分配
Two standards for serial interfaces you may also see are RS-422 and RS-574.
您可能还会看到 RS-422 和 RS-574 这两种串行接口标准。
RS-422 uses lower voltages and differential signals to allow cable lengths up to about 1000ft (300m).
RS-422 使用较低的电压和差分信号,允许电缆长度达到约 1000 英尺(300 米)。
RS-574 defines the 9-pin PC serial connector and voltages.
RS-574 定义了 9 针 PC 串行连接器和电压。
Signal Definitions
信号定义
The RS-232 standard defines some 18 different signals for serial communications.
RS-232 标准为串行通信定义了大约 18 种不同的信号。
Of these, only six are generally available in the UNIX environment.
在 UNIX 环境中,通常只提供其中的六种。
GND - Logic Ground
GND - 逻辑地
Technically the logic ground is not a signal, but without it none of the other signals will operate.
从技术上讲,逻辑地并不是一个信号,但没有它,其他信号都无法工作。
Basically, the logic ground acts as a reference voltage so that the electronics know which voltages are positive or negative.
基本上,逻辑地作为参考电压,以便电子设备知道哪些电压是正的,哪些是负的。
TXD - Transmitted Data
TXD - 发送数据
The TXD signal carries data transmitted from your workstation to the computer or device on the other end (like a MODEM).
TXD 信号携带从您的工作站发送到另一端的计算机或设备(如调制解调器)的数据。
A mark voltage is interpreted as a value of 1, while a space voltage is interpreted as a value of 0.
标记电压被解释为值 1,而空格电压被解释为值 0。
RXD - Received Data
RXD - 接收数据
The RXD signal carries data transmitted from the computer or device on the other end to your workstation.
RXD 信号携带从另一端的计算机或设备发送到您的工作站的数据。
Like TXD, mark and space voltages are interpreted as 1 and 0, respectively.
与 TXD 一样,标记和空格电压分别被解释为 1 和 0。
DCD - Data Carrier Detect
DCD - 数据载波检测
The DCD signal is received from the computer or device on the other end of your serial cable.
DCD 信号是从您的串行电缆另一端的计算机或设备接收的。
A space voltage on this signal line indicates that the computer or device is currently connected or on line.
此信号线上的空格电压表明计算机或设备当前已连接或在线。
DCD is not always used or available.
DCD 并不总是被使用或可用。
DTR - Data Terminal Ready
DTR - 数据终端就绪
The DTR signal is generated by your workstation and tells the computer or device on the other end that you are ready (a space voltage) or not-ready (a mark voltage).
DTR 信号由您的工作站生成,并告诉另一端的计算机或设备您已准备好(空格电压)或未准备好(标记电压)。
DTR is usually enabled automatically whenever you open the serial interface on the workstation.
通常,每当您在工作站上打开串行接口时,DTR 会自动启用。
CTS - Clear To Send
CTS - 允许发送
The CTS signal is received from the other end of the serial cable.
CTS 信号是从串行电缆的另一端接收的。
A space voltage indicates that it is alright to send more serial data from your workstation.
空格电压表示可以从您的工作站发送更多的串行数据。
CTS is usually used to regulate the flow of serial data from your workstation to the other end.
CTS 通常用于调节从您的工作站到另一端的串行数据流。
RTS - Request To Send
RTS - 请求发送
The RTS signal is set to the space voltage by your workstation to indicate that more data is ready to be sent.
您的工作站将 RTS 信号设置为空格电压,以表示有更多数据准备好发送。
Like CTS, RTS helps to regulate the flow of data between your workstation and the computer or device on the other end of the serial cable.
与 CTS 一样,RTS 有助于调节工作站与串行电缆另一端的计算机或设备之间的数据流。
Most workstations leave this signal set to the space voltage all the time.
大多数工作站始终将此信号设置为空格电压。
Asynchronous Communications
异步通信
For the computer to understand the serial data coming into it, it needs some way to determine where one character ends and the next begins.
为了让计算机理解传入的串行数据,它需要某种方式来确定一个字符在哪里结束,下一个字符在哪里开始。
This guide deals exclusively with asynchronous serial data.
本指南仅涉及异步串行数据。
In asynchronous mode the serial data line stays in the mark (1) state until a character is transmitted.
在异步模式下,串行数据线保持在标记(1)状态,直到传输一个字符。
A start bit preceeds each character and is followed immediately by each bit in the character, an optional parity bit, and one or more stop bits.
每个字符前面都有一个起始位,紧接着是字符中的每一位、一个可选的奇偶校验位和一个或多个停止位。
The start bit is always a space (0) and tells the computer that new serial data is available.
起始位始终为空格(0),它告诉计算机有新的串行数据可用。
Data can be sent or received at any time, thus the name asynchronous.
数据可以在任何时间发送或接收,因此得名为异步。
Figure 1 - Asynchronous Data Transmission
图 1 - 异步数据传输
The optional parity bit is a simple sum of the data bits indicating whether or not the data contains an even or odd number of 1 bits.
可选的奇偶校验位是对数据位的简单求和,表明数据中是否包含偶数或奇数个 1 位。
With even parity, the parity bit is 0 if there is an even number of 1’s in the character.
在偶校验中,如果字符中有偶数个 1,则奇偶校验位为 0。
With odd parity, the parity bit is 0 if there is an odd number of 1’s in the data.
在奇校验中,如果数据中有奇数个 1,则奇偶校验位为 0。
You may also hear the terms space parity, mark parity, and no parity.
您还可能听到“空格校验”、“标记校验”和“无校验”这些术语。
Space parity means that the parity bit is always 0, while mark parity means the bit is always 1.
空格校验意味着奇偶校验位始终为 0,而标记校验意味着该位始终为 1。
No parity means that no parity bit is present or transmitted.
无校验意味着没有奇偶校验位存在或传输。
The remaining bits are called stop bits.
剩余的位称为停止位。
There can be 1, 1.5, or 2 stop bits between characters and they always have a value of 1.
字符之间可以有 1 个、1.5 个或 2 个停止位,它们的值始终为 1。
Stop bits traditionally were used to give the computer time to process the previous character, but now only serve to synchronize the receiving computer to the incoming characters.
停止位传统上用于给计算机时间处理前一个字符,但现在仅用于将接收计算机与传入字符同步。
Asynchronous data formats are usually expressed as “8N1”, “7E1”, and so forth.
异步数据格式通常表示为“8N1”、“7E1”等。
These stand for “8 data bits, no parity, 1 stop bit” and “7 data bits, even parity, 1 stop bit” respectively.
这些分别表示“8 个数据位,无校验,1 个停止位”和“7 个数据位,偶校验,1 个停止位”。
What Are Full Duplex and Half Duplex?
什么是全双工和半双工?
Full duplex means that the computer can send and receive data simultaneously - there are two separate data channels (one coming in, one going out).
全双工表示计算机可以同时发送和接收数据——有两个独立的数据通道(一个用于接收,一个用于发送)。
Half duplex means that the computer cannot send or receive data at the same time.
半双工表示计算机不能同时发送或接收数据。
Usually this means there is only a single data channel to talk over.
通常这意味着只有一个数据通道用于通信。
This does not mean that any of the RS-232 signals are not used.
这并不意味着不使用任何 RS-232 信号。
Rather, it usually means that the communications link uses some standard other than RS-232 that does not support full duplex operation.
相反,它通常意味着通信链路使用了某种非 RS-232 的标准,该标准不支持全双工操作。
Flow Control
流量控制
It is often necessary to regulate the flow of data when transferring data between two serial interfaces.
在两个串行接口之间传输数据时,通常需要调节数据流。
This can be due to limitations in an intermediate serial communications link, one of the serial interfaces, or some storage media.
这可能是由于中间串行通信链路、其中一个串行接口或某些存储介质的限制。
Two methods are commonly used for asynchronous data.
异步数据通常使用两种方法。
The first method is often called “software” flow control and uses special characters to start (XON or DC1, 021 octal) or stop (XOFF or DC3, 023 octal) the flow of data.
第一种方法通常称为“软件”流量控制,它使用特殊字符来开始(XON 或 DC1,八进制 021)或停止(XOFF 或 DC3,八进制 023)数据流。
These characters are defined in the American Standard Code for Information Interchange (“ASCII”).
这些字符在“美国信息交换标准代码”(ASCII)中有定义。
While these codes are useful when transferring textual information, they cannot be used when transferring other types of information without special programming.
虽然这些代码在传输文本信息时很有用,但在没有特殊编程的情况下,它们不能用于传输其他类型的信息。
The second method is called “hardware” flow control and uses the RS-232 CTS and RTS signals instead of special characters.
第二种方法称为“硬件”流量控制,它使用 RS-232 的 CTS 和 RTS 信号,而不是特殊字符。
The receiver sets CTS to the space voltage when it is ready to receive more data and to the mark voltage when it is not ready.
接收器在准备好接收更多数据时将 CTS 设置为空格电压,而在未准备好时将其设置为标记电压。
Likewise, the sender sets RTS to the space voltage when it is ready to send more data.
同样,发送方在准备好发送更多数据时将 RTS 设置为空格电压。
Because hardware flow control uses a separate set of signals, it is much faster than software flow control which needs to send or receive multiple bits of information to do the same thing.
由于硬件流量控制使用了一组独立的信号,因此它比需要发送或接收多个比特信息来完成相同任务的软件流量控制要快得多。
CTS/RTS flow control is not supported by all hardware or operating systems.
并非所有硬件或操作系统都支持 CTS/RTS 流量控制。
What Is a Break?
什么是中断?
Normally a receive or transmit data signal stays at the mark voltage until a new character is transferred.
通常,接收或发送数据信号会保持在标记电压,直到传输新的字符。
If the signal is dropped to the space voltage for a long period of time, usually 1/4 to 1/2 second, then a break condition is said to exist.
如果信号长时间(通常为 1/4 到 1/2 秒)降至空格电压,则认为存在中断条件。
A break is sometimes used to reset a communications line or change the operating mode of communications hardware like a MODEM.
中断有时用于重置通信线路或更改通信硬件(如调制解调器)的操作模式。
Chapter 3, Talking to MODEMs covers these applications in more depth.
第 3 章“与调制解调器通信”将更深入地介绍这些应用。
Synchronous Communications
同步通信
Unlike asynchronous data, synchronous data appears as a constant stream of bits.
与异步数据不同,同步数据表现为连续的比特流。
To read the data on the line, the computer must provide or receive a common bit clock so that both the sender and receiver are synchronized.
为了在线上读取数据,计算机必须提供或接收一个共同的比特时钟,以便发送方和接收方能够同步。
Even with this synchronization, the computer must mark the beginning of the data somehow.
即使有了这种同步,计算机也必须以某种方式标记数据的开始。
The most common way of doing this is to use a data packet protocol like Serial Data Link Control (“SDLC”) or High-Speed Data Link Control (“HDLC”).
最常见的方法是使用像串行数据链路控制(“SDLC”)或高速数据链路控制(“HDLC”)这样的数据包协议。
Each protocol defines certain bit sequences to represent the beginning and end of a data packet.
每种协议都定义了某些比特序列来表示数据包的开始和结束。
Each also defines a bit sequence that is used when there is no data.
每种协议还定义了在没有数据时使用的比特序列。
These bit sequences allow the computer to see the beginning of a data packet.
这些比特序列使计算机能够看到数据包的开始。
Because synchronous protocols do not use per-character synchronization bits they typically provide at least a 25% improvement in performance over asynchronous communications and are suitable for remote networking and configurations with more than two serial interfaces.
由于同步协议不使用每个字符的同步比特,因此它们通常比异步通信至少提高了 25% 的性能,并且适用于远程网络和拥有超过两个串行接口的配置。
Despite the speed advantages of synchronous communications, most RS-232 hardware does not support it due to the extra hardware and software required.
尽管同步通信具有速度优势,但由于需要额外的硬件和软件,大多数 RS-232 硬件并不支持它。
Accessing Serial Ports
访问串行端口
Like all devices, UNIX provides access to serial ports via device files.
与所有设备一样,UNIX 通过设备文件提供对串行端口的访问。
To access a serial port you simply open the corresponding device file.
要访问串行端口,只需打开相应的设备文件。
Serial Port Files
串行端口文件
Each serial port on a UNIX system has one or more device files (files in the /dev
directory) associated with it:
UNIX 系统上的每个串行端口都与一个或多个设备文件(位于 /dev
目录中的文件)相关联:
System | Port 1 | Port 2 |
---|---|---|
IRIX® | /dev/ttyf1 | /dev/ttyf2 |
HP-UX | /dev/tty1p0 | /dev/tty2p0 |
Solaris®/SunOS® | /dev/ttya | /dev/ttyb |
Linux® | /dev/ttyS0 | /dev/ttyS1 |
Digital UNIX® | /dev/tty01 | /dev/tty02 |
表 2 - 串行端口设备文件
Opening a Serial Port
打开串行端口
Since a serial port is a file, the open(2) function is used to access it.
由于串行端口是一个文件,因此使用 open(2) 函数来访问它。
The one hitch with UNIX is that device files are usually not accessible by normal users.
UNIX 的一个问题是设备文件通常对普通用户不可访问。
Workarounds include changing the access permissions to the file(s) in question, running your program as the super-user (root), or making your program set-userid so that it runs as the owner of the device file (not recommended for obvious security reasons…)
解决方法包括更改相关文件的访问权限,以超级用户(root)身份运行您的程序,或者将您的程序设置为 set-userid,使其以设备文件的所有者身份运行(由于明显的安全原因,不推荐此方法……)
For now we’ll assume that the file is accessible by all users.
目前,我们假设该文件对所有用户都可访问。
The code to open serial port 1 on a PC running Linux is show in Listing 1.
在运行 Linux 的 PC 上打开串行端口 1 的代码如清单 1 所示。
Listing 1 - Opening a serial port.
清单 1 - 打开串行端口。
#include <stdio.h> /* Standard input/output definitions */
#include <string.h> /* String function definitions */
#include <unistd.h> /* UNIX standard function definitions */
#include <fcntl.h> /* File control definitions */
#include <errno.h> /* Error number definitions */
#include <termios.h> /* POSIX terminal control definitions */
/*
* 'open_port()' - Open serial port 1.
*
* Returns the file descriptor on success or -1 on error.
*/
int
open_port(void)
{
int fd; /* File descriptor for the port */
fd = open("/dev/ttyS0", O_RDWR | O_NOCTTY | O_NDELAY);
if (fd == -1)
{
/*
* Could not open the port.
*/
perror("open_port: Unable to open /dev/ttyS0 - ");
}
else
fcntl(fd, F_SETFL, 0);
return (fd);
}
Other systems would require the corresponding device file name, but otherwise the code is the same.
其他系统需要相应的设备文件名,但其他代码是相同的。
Open Options
打开选项
You’ll notice that when we opened the device file we used two other flags along with the read+write mode:
您会注意到,我们在打开设备文件时,除了读写模式外,还使用了两个其他标志:
fd = open("/dev/ttyS0", O_RDWR | O_NOCTTY | O_NDELAY);
The O_NOCTTY flag tells UNIX that this program doesn’t want to be the “controlling terminal” for that port.
O_NOCTTY 标志告诉 UNIX,该程序不想成为该端口的“控制终端”。
If you don’t specify this then any input (such as keyboard abort signals and so forth) will affect your process.
如果不指定此标志,则任何输入(如键盘中断信号等)都将影响您的进程。
Programs like getty(1M/8) use this feature when starting the login process, but normally a user program does not want this behavior.
像 getty(1M/8) 这样的程序在启动登录过程时会使用此功能,但通常用户程序不希望出现这种行为。
The O_NDELAY flag tells UNIX that this program doesn’t care what state the DCD signal line is in - whether the other end of the port is up and running.
O_NDELAY 标志告诉 UNIX,该程序不关心 DCD 信号线的状态——端口的另一端是否已启动并运行。
If you do not specify this flag, your process will be put to sleep until the DCD signal line is the space voltage.
如果不指定此标志,您的进程将被挂起,直到 DCD 信号线为空格电压。
Writing Data to the Port
向端口写入数据
Writing data to the port is easy - just use the write(2) system call to send data it:
向端口写入数据很简单,只需使用 write(2) 系统调用来发送数据:
n = write(fd, "ATZ\r", 4);
if (n < 0)
fputs("write() of 4 bytes failed!\n", stderr);
The write function returns the number of bytes sent or -1 if an error occurred.
write 函数返回发送的字节数,或者在发生错误时返回 -1。
Usually the only error you’ll run into is EIO when a MODEM or data link drops the Data Carrier Detect (DCD) line.
通常,您遇到的唯一错误是 EIO,当调制解调器或数据链路断开数据载波检测(DCD)线路时。
This condition will persist until you close the port.
这种情况会一直持续,直到您关闭端口。
Reading Data from the Port
从端口读取数据
Reading data from a port is a little trickier.
从端口读取数据稍微复杂一些。
When you operate the port in raw data mode, each read(2) system call will return the number of characters that are actually available in the serial input buffers.
当您以原始数据模式操作端口时,每个 read(2) 系统调用将返回实际在串行输入缓冲区中可用的字符数。
If no characters are available, the call will block (wait) until characters come in, an interval timer expires, or an error occurs.
如果没有可用的字符,调用将阻塞(等待),直到字符到达、间隔计时器到期或发生错误。
The read function can be made to return immediately by doing the following:
可以通过以下方式使 read 函数立即返回:
fcntl(fd, F_SETFL, FNDELAY);
The FNDELAY option causes the read function to return 0 if no characters are available on the port.
FNDELAY 选项使 read 函数在端口上没有可用字符时返回 0。
To restore normal (blocking) behavior, call fcntl() without the FNDELAY option:
要恢复正常的(阻塞)行为,请在不使用 FNDELAY 选项的情况下调用 fcntl() :
fcntl(fd, F_SETFL, 0);
This is also used after opening a serial port with the O_NDELAY option.
在使用 O_NDELAY 选项打开串行端口后,也会使用此方法。
Closing a Serial Port
关闭串行端口
To close the serial port, just use the close system call:
要关闭串行端口,只需使用 close 系统调用:
close(fd);
Closing a serial port will also usually set the DTR signal low which causes most MODEMs to hang up.
关闭串行端口通常还会将 DTR 信号设置为低电平,这会导致大多数调制解调器挂断。
Chapter 2, Configuring the Serial Port
第 2 章,配置串行端口
This chapter discusses how to configure a serial port from C using the POSIX termios interface.
本章讨论如何使用 POSIX termios 接口从 C 语言配置串行端口。
The POSIX Terminal Interface
POSIX 终端接口
Most systems support the POSIX terminal (serial) interface for changing parameters such as baud rate, character size, and so on.
大多数系统都支持 POSIX 终端(串行)接口,用于更改波特率、字符大小等参数。
The first thing you need to do is include the file <termios.h>
; this defines the terminal control structure as well as the POSIX control functions.
首先需要包含文件 <termios.h>
,它定义了终端控制结构以及 POSIX 控制函数。
The two most important POSIX functions are tcgetattr(3) and tcsetattr(3).
最重要的两个 POSIX 函数是 tcgetattr(3) 和 tcsetattr(3)。
These get and set terminal attributes, respectively; you provide a pointer to a termios structure that contains all of the serial options available:
这些函数分别用于获取和设置终端属性,您需要提供一个指向包含所有可用串行选项的 termios 结构的指针:
Member | Description |
---|---|
c_cflag | Control options |
c_lflag | Line options |
c_iflag | Input options |
c_oflag | Output options |
c_cc | Control characters |
c_ispeed | Input baud (new interface) |
c_ospeed | Output baud (new interface) |
表 3 - Termios 结构成员
Control Options
控制选项
The c_cflag member controls the baud rate, number of data bits, parity, stop bits, and hardware flow control.
c_cflag 成员控制波特率、数据位数、奇偶校验、停止位和硬件流量控制。
There are constants for all of the supported configurations.
所有支持的配置都有对应的常量。
Constant | Description |
---|---|
CBAUD | Bit mask for baud rate |
B0 | 0 baud (drop DTR) |
B50 | 50 baud |
B75 | 75 baud |
B110 | 110 baud |
B134 | 134.5 baud |
B150 | 150 baud |
B200 | 200 baud |
B300 | 300 baud |
B600 | 600 baud |
B1200 | 1200 baud |
B1800 | 1800 baud |
B2400 | 2400 baud |
B4800 | 4800 baud |
B9600 | 9600 baud |
B19200 | 19200 baud |
B38400 | 38400 baud |
B57600 | 57,600 baud |
B76800 | 76,800 baud |
B115200 | 115,200 baud |
EXTA | External rate clock |
EXTB | External rate clock |
CSIZE | Bit mask for data bits |
CS5 | 5 data bits |
CS6 | 6 data bits |
CS7 | 7 data bits |
CS8 | 8 data bits |
CSTOPB | 2 stop bits (1 otherwise) |
CREAD | Enable receiver |
PARENB | Enable parity bit |
PARODD | Use odd parity instead of even |
HUPCL | Hangup (drop DTR) on last close |
CLOCAL | Local line - do not change “owner” of port |
LOBLK | Block job control output |
CNEW_RTSCTS CRTSCTS | Enable hardware flow control (not supported on all platforms) |
表 4 - c_cflag 成员的常量
The c_cflag member contains two options that should always be enabled, CLOCAL and CREAD.
c_cflag 成员包含两个应始终启用的选项:CLOCAL 和 CREAD。
These will ensure that your program does not become the ‘owner’ of the port subject to sporatic job control and hangup signals, and also that the serial interface driver will read incoming data bytes.
这些选项可以确保您的程序不会成为端口的“所有者”,从而避免受到随机作业控制和挂断信号的影响,并且确保串行接口驱动程序会读取传入的数据字节。
The baud rate constants ( CBAUD, B9600, etc.) are used for older interfaces that lack the c_ispeed and c_ospeed members.
波特率常量(CBAUD、B9600 等)用于缺少 c_ispeed 和 c_ospeed 成员的旧接口。
See the next section for information on the POSIX functions used to set the baud rate.
有关用于设置波特率的 POSIX 函数的信息,请参见下一节。
Never initialize the c_cflag (or any other flag) member directly; you should always use the bitwise AND, OR, and NOT operators to set or clear bits in the members.
切勿直接初始化 c_cflag(或任何其他标志)成员,您应始终使用按位与、或和非运算符来设置或清除成员中的位。
Different operating system versions (and even patches) can and do use the bits differently, so using the bitwise operators will prevent you from clobbering a bit flag that is needed in a newer serial driver.
不同的操作系统版本(甚至补丁)可能会以不同的方式使用这些位,因此使用按位运算符可以防止您覆盖在较新的串行驱动程序中需要的位标志。
Setting the Baud Rate
设置波特率
The baud rate is stored in different places depending on the operating system.
波特率的存储位置因操作系统而异。
Older interfaces store the baud rate in the c_cflag member using one of the baud rate constants in table 4, while newer implementations provide the c_ispeed and c_ospeed members that contain the actual baud rate value.
旧接口使用表 4 中的波特率常量之一将波特率存储在 c_cflag 成员中,而新实现提供了包含实际波特率值的 c_ispeed 和 c_ospeed 成员。
The cfsetospeed(3) and cfsetispeed(3) functions are provided to set the baud rate in the termios structure regardless of the underlying operating system interface.
无论底层操作系统接口如何,cfsetospeed(3) 和 cfsetispeed(3) 函数都可用于在 termios 结构中设置波特率。
Typically you’d use the code in Listing 2 to set the baud rate.
通常,您可以使用清单 2 中的代码来设置波特率。
Listing 2 - Setting the baud rate.
清单 2 - 设置波特率。
struct termios options;
/*
* Get the current options for the port...
*/
tcgetattr(fd, &options);
/*
* Set the baud rates to 19200...
*/
cfsetispeed(&options, B19200);
cfsetospeed(&options, B19200);
/*
* Enable the receiver and set local mode...
*/
options.c_cflag |= (CLOCAL | CREAD);
/*
* Set the new options for the port...
*/
tcsetattr(fd, TCSANOW, &options);
The tcgetattr(3) function fills the termios structure you provide with the current serial port configuration.
tcgetattr(3) 函数会用当前串行端口配置填充您提供的 termios 结构。
After we set the baud rates and enable local mode and serial data receipt, we select the new configuration using tcsetattr(3).
在我们设置波特率并启用本地模式和串行数据接收后,我们使用 tcsetattr(3) 选择新配置。
The TCSANOW constant specifies that all changes should occur immediately without waiting for output data to finish sending or input data to finish receiving.
TCSANOW 常量指定所有更改应立即生效,而不等待输出数据完成发送或输入数据完成接收。
There are other constants to wait for input and output to finish or to flush the input and output buffers.
还有其他常量用于等待输入和输出完成,或清空输入和输出缓冲区。
Most systems do not support different input and output speeds, so be sure to set both to the same value for maximum portability.
大多数系统不支持不同的输入和输出速度,因此为了确保最大的可移植性,请确保将两者设置为相同的值。
Constant | Description |
---|---|
TCSANOW | Make changes now without waiting for data to complete |
TCSADRAIN | Wait until everything has been transmitted |
TCSAFLUSH | Flush input and output buffers and make the change |
表 5 - tcsetattr 的常量
Setting the Character Size
设置字符大小
Unlike the baud rate, there is no convenience function to set the character size.
与波特率不同,没有专门的函数来设置字符大小。
Instead you must do a little bitmasking to set things up.
相反,您需要手动进行一些位掩码操作。
The character size is specified in bits:
字符大小以比特为单位指定:
options.c_cflag &= ~CSIZE; /* Mask the character size bits */
options.c_cflag |= CS8; /* Select 8 data bits */
Setting Parity Checking
设置奇偶校验
Like the character size you must manually set the parity enable and parity type bits.
与字符大小一样,您需要手动设置奇偶校验使能位和奇偶校验类型位。
UNIX serial drivers support even, odd, and no parity bit generation.
UNIX 串行驱动程序支持生成偶校验、奇校验和无校验位。
Space parity can be simulated with clever coding.
可以通过巧妙的编程模拟空格校验。
-
No parity (8N1):
无校验(8N1):
options.c_cflag &= ~PARENB;
options.c_cflag &= ~CSTOPB;
options.c_cflag &= ~CSIZE;
options.c_cflag |= CS8;
-
Even parity (7E1):
偶校验(7E1):
options.c_cflag |= PARENB; options.c_cflag &= ~PARODD; options.c_cflag &= ~CSTOPB; options.c_cflag &= ~CSIZE; options.c_cflag |= CS7;
-
Odd parity (7O1):
奇校验(7O1):
options.c_cflag |= PARENB; options.c_cflag |= PARODD; options.c_cflag &= ~CSTOPB; options.c_cflag &= ~CSIZE; options.c_cflag |= CS7;
-
Space parity is setup the same as no parity (7S1):
空格校验的设置与无校验(7S1)相同:
options.c_cflag &= ~PARENB; options.c_cflag &= ~CSTOPB; options.c_cflag &= ~CSIZE; options.c_cflag |= CS8;
Setting Hardware Flow Control
设置硬件流量控制
Some versions of UNIX support hardware flow control using the CTS (Clear To Send) and RTS (Request To Send) signal lines.
某些版本的 UNIX 支持使用 CTS(允许发送)和 RTS(请求发送)信号线进行硬件流量控制。
If the CNEW_RTSCTS or CRTSCTS constants are defined on your system then hardware flow control is probably supported.
如果您的系统定义了 CNEW_RTSCTS 或 CRTSCTS 常量,则可能支持硬件流量控制。
Do the following to enable hardware flow control:
要启用硬件流量控制,请执行以下操作:
options.c_cflag |= CNEW_RTSCTS; /* Also called CRTSCTS */
Similarly, to disable hardware flow control:
同样,要禁用硬件流量控制,请执行以下操作:
options.c_cflag &= ~CNEW_RTSCTS;
Local Options
本地选项
The local modes member c_lflag controls how input characters are managed by the serial driver.
本地模式成员 c_lflag 控制串行驱动程序如何管理输入字符。
In general you will configure the c_lflag member for canonical or raw input.
通常,您会将 c_lflag 成员配置为 canonical(规范)或 raw(原始)输入。
Constant | Description |
---|---|
ISIG | Enable SIGINTR, SIGSUSP, SIGDSUSP, and SIGQUIT signals |
ICANON | Enable canonical input (else raw) |
XCASE | Map uppercase \lowercase (obsolete) |
ECHO | Enable echoing of input characters |
ECHOE | Echo erase character as BS-SP-BS |
ECHOK | Echo NL after kill character |
ECHONL | Echo NL |
NOFLSH | Disable flushing of input buffers after interrupt or quit characters |
IEXTEN | Enable extended functions |
ECHOCTL | Echo control characters as ^char and delete as ~? |
ECHOPRT | Echo erased character as character erased |
ECHOKE | BS-SP-BS entire line on line kill |
FLUSHO | Output being flushed |
PENDIN | Retype pending input at next read or input char |
TOSTOP | Send SIGTTOU for background output |
表 6 - c_lflag 成员的常量
Choosing Canonical Input
选择规范输入
Canonical input is line-oriented.
规范输入是面向行的。
Input characters are put into a buffer which can be edited interactively by the user until a CR (carriage return) or LF (line feed) character is received.
输入字符被放入一个缓冲区,用户可以交互式地编辑这些字符,直到接收到 CR(回车)或 LF(换行)字符。
When selecting this mode you normally select the ICANON, ECHO, and ECHOE options:
选择此模式时,通常会选择 ICANON、ECHO 和 ECHOE 选项:
options.c_lflag |= (ICANON | ECHO | ECHOE);
Choosing Raw Input
选择原始输入
Raw input is unprocessed.
原始输入是未经处理的。
Input characters are passed through exactly as they are received, when they are received.
输入字符将按照接收时的原样传递。
Generally you’ll deselect the ICANON, ECHO, ECHOE, and ISIG options when using raw input:
通常在使用原始输入时,会取消选择 ICANON、ECHO、ECHOE 和 ISIG 选项:
options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
A Note About Input Echo
关于输入回显的注意事项
Never enable input echo ( ECHO, ECHOE) when sending commands to a MODEM or other computer that is echoing characters, as you will generate a feedback loop between the two serial interfaces!
切勿在向调制解调器或其他正在回显字符的计算机发送命令时启用输入回显(ECHO, ECHOE),否则您将在两个串行接口之间产生反馈环路!
Input Options
输入选项
The input modes member c_iflag controls any input processing that is done to characters received on the port.
输入模式成员 c_iflag 控制对端口接收的字符进行的任何输入处理。
Like the c_cflag field, the final value stored in c_iflag is the bitwise OR of the desired options.
与 c_cflag 字段一样,存储在 c_iflag 中的最终值是所需选项的按位或。
Constant | Description |
---|---|
INPCK | Enable parity check |
IGNPAR | Ignore parity errors |
PARMRK | Mark parity errors |
ISTRIP | Strip parity bits |
IXON | Enable software flow control (outgoing) |
IXOFF | Enable software flow control (incoming) |
IXANY | Allow any character to start flow again |
IGNBRK | Ignore break condition |
BRKINT | Send a SIGINT when a break condition is detected |
INLCR | Map NL to CR |
IGNCR | Ignore CR |
ICRNL | Map CR to NL |
IUCLC | Map uppercase to lowercase |
IMAXBEL | Echo BEL on input line too long |
表 7 - c_iflag 成员的常量
Setting Input Parity Options
设置输入奇偶校验选项
You should enable input parity checking when you have enabled parity in the c_cflag member ( PARENB).
当您在 c_cflag 成员中启用了奇偶校验(PARENB)时,应该启用输入奇偶校验检查。
The relevant constants for input parity checking are INPCK, IGNPAR, PARMRK, and ISTRIP.
输入奇偶校验检查相关的常量是 INPCK、IGNPAR、PARMRK 和 ISTRIP。
Generally you will select INPCK and ISTRIP to enable checking and stripping of the parity bit:
通常会选择 INPCK 和 ISTRIP 以启用奇偶校验位的检查和剥离:
options.c_iflag |= (INPCK | ISTRIP);
IGNPAR is a somewhat dangerous option that tells the serial driver to ignore parity errors and pass the incoming data through as if no errors had occurred.
IGNPAR 是一个相对危险的选项,它告诉串行驱动程序忽略奇偶校验错误,并像没有发生错误一样传递传入的数据。
This can be useful for testing the quality of a communications link, but in general is not used for practical reasons.
这可用于测试通信链路的质量,但通常由于实际原因而不使用。
PARMRK causes parity errors to be “marked” in the input stream using special characters.
PARMRK 会导致奇偶校验错误在输入流中使用特殊字符进行“标记”。
If IGNPAR is enabled, a NUL character (000 octal) is sent to your program before every character with a parity error.
如果启用了 IGNPAR,则在每个带有奇偶校验错误的字符之前,会向您的程序发送一个 NUL 字符(八进制 000)。
Otherwise, a DEL (177 octal) and NUL character is sent along with the bad character.
否则,会发送一个 DEL(八进制 177)和 NUL 字符,以及错误的字符。
Setting Software Flow Control
设置软件流量控制
Software flow control is enabled using the IXON, IXOFF, and IXANY constants:
使用 IXON、IXOFF 和 IXANY 常量启用软件流量控制:
options.c_iflag |= (IXON | IXOFF | IXANY);
To disable software flow control simply mask those bits:
要禁用软件流量控制,只需屏蔽这些位:
options.c_iflag &= ~(IXON | IXOFF | IXANY);
The XON (start data) and XOFF (stop data) characters are defined in the c_cc array described below.
XON(开始数据)和 XOFF(停止数据)字符在下面描述的 c_cc 数组中定义。
Output Options
输出选项
The c_oflag member contains output filtering options.
c_oflag 成员包含输出过滤选项。
Like the input modes, you can select processed or raw data output.
与输入模式一样,您可以选择经过处理的或原始的输出数据。
Constant | Description |
---|---|
OPOST | Postprocess output (not set = raw output) |
OLCUC | Map lowercase to uppercase |
ONLCR | Map NL to CR-NL |
OCRNL | Map CR to NL |
NOCR | No CR output at column 0 |
ONLRET | NL performs CR function |
OFILL | Use fill characters for delay |
OFDEL | Fill character is DEL |
NLDLY | Mask for delay time needed between lines |
NL0 | No delay for NLs |
NL1 | Delay further output after newline for 100 milliseconds |
CRDLY | Mask for delay time needed to return carriage to left column |
CR0 | No delay for CRs |
CR1 | Delay after CRs depending on current column position |
CR2 | Delay 100 milliseconds after sending CRs |
CR3 | Delay 150 milliseconds after sending CRs |
TABDLY | Mask for delay time needed after TABs |
TAB0 | No delay for TABs |
TAB1 | Delay after TABs depending on current column position |
TAB2 | Delay 100 milliseconds after sending TABs |
TAB3 | Expand TAB characters to spaces |
BSDLY | Mask for delay time needed after BSs |
BS0 | No delay for BSs |
BS1 | Delay 50 milliseconds after sending BSs |
VTDLY | Mask for delay time needed after VTs |
VT0 | No delay for VTs |
VT1 | Delay 2 seconds after sending VTs |
FFDLY | Mask for delay time needed after FFs |
FF0 | No delay for FFs |
FF1 | Delay 2 seconds after sending FFs |
表 8 - c_oflag 成员的常量
Choosing Processed Output
选择经过处理的输出
Processed output is selected by setting the OPOST option in the c_oflag member:
通过在 c_oflag 成员中设置 OPOST 选项来选择经过处理的输出:
options.c_oflag |= OPOST;
Of all the different options, you will only probably use the ONLCR option which maps newlines into CR-LF pairs.
在所有不同的选项中,您可能只会使用将换行符映射为回车换行符对的 ONLCR 选项。
The rest of the output options are primarily historic and date back to the time when line printers and terminals could not keep up with the serial data stream!
其他输出选项主要是历史遗留的,可以追溯到行式打印机和终端无法跟上串行数据流的时代!
Choosing Raw Output
选择原始输出
Raw output is selected by resetting the OPOST option in the c_oflag member:
通过重置 c_oflag 成员中的 OPOST 选项来选择原始输出:
options.c_oflag &= ~OPOST;
When the OPOST option is disabled, all other option bits in c_oflag are ignored.
当禁用 OPOST 选项时,c_oflag 中的所有其他选项位都将被忽略。
Control Characters
控制字符
The c_cc character array contains control character definitions as well as timeout parameters.
c_cc 字符数组包含控制字符定义以及超时参数。
Constants are defined for every element of this array.
此数组的每个元素都有对应的常量定义。
Constant | Description | Key |
---|---|---|
VINTR | Interrupt | CTRL-C |
VQUIT | Quit | CTRL-Z |
VERASE | Erase | Backspace (BS) |
VKILL | Kill-line | CTRL-U |
VEOF | End-of-file | CTRL-D |
VEOL | End-of-line | Carriage return (CR) |
VEOL2 | Second end-of-line | Line feed (LF) |
VMIN | Minimum number of characters to read | - |
VSTART | Start flow | CTRL-Q (XON) |
VSTOP | Stop flow | CTRL-S (XOFF) |
VTIME | Time to wait for data (tenths of seconds) | - |
表 9 - c_cc 成员中的控制字符
Setting Software Flow Control Characters
设置软件流量控制字符
The VSTART and VSTOP elements of the c_cc array contain the characters used for software flow control.
c_cc 数组中的 VSTART 和 VSTOP 元素包含用于软件流量控制的字符。
Normally they should be set to DC1 (021 octal) and DC3 (023 octal) which represent the ASCII standard XON and XOFF characters.
通常,它们应设置为 DC1(八进制 021)和 DC3(八进制 023),分别表示 ASCII 标准的 XON 和 XOFF 字符。
Setting Read Timeouts
设置读取超时
UNIX serial interface drivers provide the ability to specify character and packet timeouts.
UNIX 串行接口驱动程序提供了指定字符和数据包超时的功能。
Two elements of the c_cc array are used for timeouts: VMIN and VTIME.
c_cc 数组中的两个元素用于超时:VMIN 和 VTIME。
Timeouts are ignored in canonical input mode or when the NDELAY option is set on the file via open or fcntl.
在规范输入模式下,或者通过 open 或 fcntl 在文件上设置了 NDELAY 选项时,超时将被忽略。
VMIN specifies the minimum number of characters to read.
VMIN 指定要读取的最少字符数。
If it is set to 0, then the VTIME value specifies the time to wait for every character read.
如果将其设置为 0,则 VTIME 值指定每次读取字符的等待时间。
Note that this does not mean that a read call for N bytes will wait for N characters to come in.
请注意,这并不意味着对 N 字节的 read 调用会等待 N 个字符到达。
Rather, the timeout will apply to the first character and the read call will return the number of characters immediately available (up to the number you request).
相反,超时将应用于第一个字符,而 read 调用将返回立即可用的字符数(最多为您请求的字符数)。
If VMIN is non-zero, VTIME specifies the time to wait for the first character read.
如果 VMIN 不为零,则 VTIME 指定等待第一个字符读取的时间。
If a character is read within the time given, any read will block (wait) until all VMIN characters are read.
如果在给定时间内读取了一个字符,则任何读取操作都会阻塞(等待),直到读取了所有 VMIN 字符。
That is, once the first character is read, the serial interface driver expects to receive an entire packet of characters ( VMIN bytes total).
也就是说,一旦读取了第一个字符,串行接口驱动程序期望接收一个完整的字符数据包(总共 VMIN 字节)。
If no character is read within the time allowed, then the call to read returns 0.
如果在允许的时间内没有读取任何字符,则 read 调用返回 0。
This method allows you to tell the serial driver you need exactly N bytes and any read call will return 0 or N bytes.
此方法允许您告诉串行驱动程序您需要正好 N 个字节,任何 read 调用都将返回 0 或 N 个字节。
However, the timeout only applies to the first character read, so if for some reason the driver misses one character inside the N byte packet then the read call could block forever waiting for additional input characters.
然而,超时仅适用于第一个字符的读取,因此如果驱动程序由于某种原因错过了 N 字节数据包中的一个字符,那么 read 调用可能会无限期地阻塞,等待额外的输入字符。
VTIME specifies the amount of time to wait for incoming characters in tenths of seconds.
VTIME 指定以十分之一秒为单位等待传入字符的时间。
If VTIME is set to 0 (the default), reads will block (wait) indefinitely unless the NDELAY option is set on the port with open or fcntl.
如果将 VTIME 设置为 0(默认值),则除非使用 open 或 fcntl 在端口上设置了 NDELAY 选项,否则读取操作将无限期阻塞(等待)。
Chapter 3, MODEM Communications
第 3 章,调制解调器通信
This chapter covers the basics of dialup telephone Modulator/Demodulator (MODEM) communications.
本章介绍了拨号电话调制解调器(MODEM)通信的基础知识。
Examples are provided for MODEMs that use the de facto standard “AT” command set.
为使用事实上的标准“AT”命令集的调制解调器提供了示例。
What Is a MODEM?
什么是调制解调器?
MODEMs are devices that modulate serial data into frequencies that can be transferred over an analog data link such as a telephone line or cable TV connection.
调制解调器是将串行数据调制成可以在模拟数据链路(如电话线或有线电视连接)上传输的频率的设备。
A standard telephone MODEM converts serial data into tones that can be passed over the phone lines; because of the speed and complexity of the conversion these tones sound more like loud screeching if you listen to them.
标准电话调制解调器将串行数据转换为可以通过电话线传输的音调;由于转换的速度和复杂性,如果您收听这些音调,它们听起来更像是刺耳的尖叫声。
Telephone MODEMs are available today that can transfer data across a telephone line at nearly 53,000 bits per second, or 53kbps.
如今,已有可以在电话线上以接近每秒 53,000 比特(53kbps)的速度传输数据的电话调制解调器。
In addition, most MODEMs use data compression technology that can increase the bit rate to well over 100kbps on some types of data.
此外,大多数调制解调器使用数据压缩技术,可以在某些类型的数据上将比特率提高到超过 100kbps。
Communicating With a MODEM
与调制解调器通信
The first step in communicating with a MODEM is to open and configure the port for raw input as shown in Listing 3.
与调制解调器通信的第一步是打开并配置端口以进行 raw(原始)输入,如清单 3 所示。
Listing 3 - Configuring the port for raw input.
清单 3 - 配置端口以进行原始输入。
int fd;
struct termios options;
/* open the port */
fd = open("/dev/ttyS0", O_RDWR | O_NOCTTY | O_NDELAY);
fcntl(fd, F_SETFL, 0);
/* get the current options */
tcgetattr(fd, &options);
/* set raw input, 1 second timeout */
options.c_cflag |= (CLOCAL | CREAD);
options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
options.c_oflag &= ~OPOST;
options.c_cc[VMIN] = 0;
options.c_cc[VTIME] = 10;
/* set the options */
tcsetattr(fd, TCSANOW, &options);
Next you need to establish communications with the MODEM.
接下来,您需要与调制解调器建立通信。
The best way to do this is by sending the “AT” command to the MODEM.
最好的方法是向调制解调器发送“AT”命令。
This also allows smart MODEMs to detect the baud you are using.
这也允许智能调制解调器检测您正在使用的波特率。
When the MODEM is connected correctly and powered on it will respond with the response “OK”.
当调制解调器正确连接并打开电源时,它将响应“OK”。
Listing 4 - Initializing the MODEM.
清单 4 - 初始化调制解调器。
int /* O - 0 = MODEM ok, -1 = MODEM bad */
init_modem(int fd) /* I - Serial port file */
{
char buffer[255]; /* Input buffer */
char *bufptr; /* Current char in buffer */
int nbytes; /* Number of bytes read */
int tries; /* Number of tries so far */
for (tries = 0; tries < 3; tries++)
{
/* send an AT command followed by a CR */
if (write(fd, "AT\r", 3) < 3)
continue;
/* read characters into our string buffer until we get a CR or NL */
bufptr = buffer;
while ((nbytes = read(fd, bufptr, buffer + sizeof(buffer) - bufptr - 1)) > 0)
{
bufptr += nbytes;
if (bufptr[-1] == '\n' || bufptr[-1] == '\r')
break;
}
/* nul terminate the string and see if we got an OK response */
*bufptr = '\0';
if (strncmp(buffer, "OK", 2) == 0)
return (0);
}
return (-1);
}
Standard MODEM Commands
标准调制解调器命令
Most MODEMs support the “AT” command set, so called because each command starts with the “AT” characters.
大多数调制解调器支持“AT”命令集,之所以这样称呼,是因为每个命令都以“AT”字符开头。
Each command is sent with the “AT” characters starting in the first column followed by the specific command and a carriage return (CR, 015 octal).
每个命令都以“AT”字符开头,位于第一列,后面跟着具体的命令和回车符(CR,八进制 015)。
After processing the command the MODEM will reply with one of several textual messages depending on the command.
处理命令后,调制解调器将根据命令回复几种文本消息之一。
ATD - Dial A Number
ATD - 拨打电话号码
The ATD command dials the specified number.
ATD 命令用于拨打指定的电话号码。
In addition to numbers and dashes you can specify tone (“T”) or pulse (“P”) dialing, pause for one second (“,”), and wait for a dialtone (“W”):
除了数字和破折号外,您还可以指定音调拨号(“T”)或脉冲拨号(“P”),暂停一秒(“,”),以及等待拨号音(“W”):
ATDT 555-1212
ATDT 18008008008W1234,1,1234
ATD T555-1212WP1234
The MODEM will reply with one of the following messages:
调制解调器将回复以下消息之一:
NO DIALTONE
BUSY
NO CARRIER
CONNECT
CONNECT baud
ATH - Hang Up
ATH - 挂断
The ATH command causes the MODEM to hang up.
ATH 命令使调制解调器挂断。
Since the MODEM must be in “command” mode you probably won’t use it during a normal phone call.
由于调制解调器必须处于“命令”模式,因此您可能不会在正常的电话通话中使用它。
Most MODEMs will also hang up if DTR is dropped; you can do this by setting the baud to 0 for at least 1 second.
如果将波特率设置为 0 至少 1 秒,大多数调制解调器也会挂断。
Dropping DTR also returns the MODEM to command mode.
降低 DTR 也会使调制解调器返回到命令模式。
After a successful hang up the MODEM will reply with “NO CARRIER”.
成功挂断后,调制解调器将回复“NO CARRIER”。
If the MODEM is still connected the “CONNECT” or “CONNECT baud” message will be sent.
如果调制解调器仍然连接,则会发送“CONNECT”或“CONNECT baud”消息。
ATZ - Reset MODEM
ATZ - 重置调制解调器
The ATZ command resets the MODEM.
ATZ 命令用于重置调制解调器。
The MODEM will reply with the string “OK”.
调制解调器将回复字符串“OK”。
Common MODEM Communication Problems
常见的调制解调器通信问题
First and foremost, don’t forget to disable input echoing.
首先且最重要的是,不要忘记禁用输入回显。
Input echoing will cause a feedback loop between the MODEM and computer.
输入回显会在调制解调器和计算机之间产生反馈环路。
Second, when sending MODEM commands you must terminate them with a carriage return (CR) and not a newline (NL).
其次,发送调制解调器命令时,必须以回车符(CR)结束,而不是换行符(NL)。
The C character constant for CR is “\r”.
CR 的 C 字符常量是 “\r”。
Finally, when dealing with a MODEM make sure you use a baud that the MODEM supports.
最后,处理调制解调器时,请确保使用调制解调器支持的波特率。
While many MODEMs do auto-baud detection, some have limits (19.2kbps is common on older MODEMs) that you must observe.
尽管许多调制解调器可以自动检测波特率,但有些调制解调器有限制(旧调制解调器常见的波特率上限为 19.2kbps),您必须遵守这些限制。
Chapter 4, Advanced Serial Programming
第 4 章,高级串行编程
This chapter covers advanced serial programming techniques using the ioctl(2) and select(2) system calls.
本章介绍了使用 ioctl(2) 和 select(2) 系统调用的高级串行编程技术。
Serial Port IOCTLs
串行端口 IOCTL
In Chapter 2, Configuring the Serial Port we used the tcgetattr and tcsetattr functions to configure the serial port.
在第 2 章“配置串行端口”中,我们使用了 tcgetattr 和 tcsetattr 函数来配置串行端口。
Under UNIX these functions use the ioctl(2) system call to do their magic.
在 UNIX 下,这些函数使用 ioctl(2) 系统调用来实现其功能。
The ioctl system call takes three arguments:
ioctl 系统调用接受三个参数:
int ioctl(int fd, int request, ...);
The fd argument specifies the serial port file descriptor.
fd 参数指定串行端口文件描述符。
The request argument is a constant defined in the <termios.h>
header file and is typically one of the constants listed in Table 10.
request 参数是在 <termios.h>
头文件中定义的一个常量,通常是表 10 中列出的常量之一。
Request | Description | POSIX Function |
---|---|---|
TCGETS | Gets the current serial port settings. | tcgetattr |
TCSETS | Sets the serial port settings immediately. | tcsetattr(fd, TCSANOW, &options) |
TCSETSF | Sets the serial port settings after flushing the input and output buffers. | tcsetattr(fd, TCSAFLUSH, &options) |
TCSETSW | Sets the serial port settings after allowing the input and output buffers to drain/empty. | tcsetattr(fd, TCSADRAIN, &options) |
TCSBRK | Sends a break for the given time. | tcsendbreak, tcdrain |
TCXONC | Controls software flow control. | tcflow |
TCFLSH | Flushes the input and/or output queue. | tcflush |
TIOCMGET | Returns the state of the “MODEM” bits. | None |
TIOCMSET | Sets the state of the “MODEM” bits. | None |
FIONREAD | Returns the number of bytes in the input buffer. | None |
表 10 - 串行端口的 IOCTL 请求
Getting the Control Signals
获取控制信号
The TIOCMGET
ioctl gets the current “MODEM” status bits, which consist of all of the RS-232 signal lines except RXD and TXD, listed in Table 11.
TIOCMGET
ioctl 获取当前的“调制解调器”状态位,这些状态位包括除 RXD 和 TXD 之外的所有 RS-232 信号线,如表 11 所示。
To get the status bits, call ioctl with a pointer to an integer to hold the bits, as shown in Listing 5.
要获取状态位,请使用指向整数的指针调用 ioctl,如清单 5 所示。
Listing 5 - Getting the MODEM status bits.
清单 5 - 获取调制解调器状态位。
#include <unistd.h>
#include <termios.h>
int fd;
int status;
ioctl(fd, TIOCMGET, &status);
Constant | Description |
---|---|
TIOCM_LE | DSR (data set ready/line enable) |
TIOCM_DTR | DTR (data terminal ready) |
TIOCM_RTS | RTS (request to send) |
TIOCM_ST | Secondary TXD (transmit) |
TIOCM_SR | Secondary RXD (receive) |
TIOCM_CTS | CTS (clear to send) |
TIOCM_CAR | DCD (data carrier detect) |
TIOCM_CD | Synonym for TIOCM_CAR |
TIOCM_RNG | RNG (ring) |
TIOCM_RI | Synonym for TIOCM_RNG |
TIOCM_DSR | DSR (data set ready) |
表 11 - 控制信号常量
Setting the Control Signals
设置控制信号
The TIOCMSET
ioctl sets the “MODEM” status bits defined above.
TIOCMSET
ioctl 设置上述定义的“调制解调器”状态位。
To drop the DTR signal you can use the code in Listing 6.
要降低 DTR 信号,可以使用清单 6 中的代码。
Listing 6 - Dropping DTR with the TIOCMSET ioctl.
清单 6 - 使用 TIOCMSET ioctl 降低 DTR。
#include <unistd.h>
#include <termios.h>
int fd;
int status;
ioctl(fd, TIOCMGET, &status);
status &= ~TIOCM_DTR;
ioctl(fd, TIOCMSET, &status);
The bits that can be set depend on the operating system, driver, and modes in use.
可以设置的位取决于操作系统、驱动程序和使用的模式。
Consult your operating system documentation for more information.
请参阅您的操作系统文档以获取更多信息。
Getting the Number of Bytes Available
获取可用字节数
The FIONREAD
ioctl gets the number of bytes in the serial port input buffer.
FIONREAD
ioctl 获取串行端口输入缓冲区中的字节数。
As with TIOCMGET
you pass in a pointer to an integer to hold the number of bytes, as shown in Listing 7.
与 TIOCMGET
一样,您需要传递一个指向整数的指针来存储字节数,如清单 7 所示。
Listing 7 - Getting the number of bytes in the input buffer.
清单 7 - 获取输入缓冲区中的字节数。
#include <unistd.h>
#include <termios.h>
int fd;
int bytes;
ioctl(fd, FIONREAD, &bytes);
This can be useful when polling a serial port for data, as your program can determine the number of bytes in the input buffer before attempting a read.
在轮询串行端口数据时,这非常有用,因为您的程序可以在尝试读取之前确定输入缓冲区中的字节数。
Selecting Input from a Serial Port
从串行端口选择输入
While simple applications can poll or wait on data coming from the serial port, most applications are not simple and need to handle input from multiple sources.
虽然简单的应用程序可以轮询或等待来自串行端口的数据,但大多数应用程序并不简单,需要处理来自多个来源的输入。
UNIX provides this capability through the select(2) system call.
UNIX 通过 select(2) 系统调用提供了这种能力。
This system call allows your program to check for input, output, or error conditions on one or more file descriptors.
该系统调用允许您的程序检查一个或多个文件描述符上的输入、输出或错误条件。
The file descriptors can point to serial ports, regular files, other devices, pipes, or sockets.
文件描述符可以指向串行端口、普通文件、其他设备、管道或套接字。
You can poll to check for pending input, wait for input indefinitely, or timeout after a specific amount of time, making the select system call extremely flexible.
您可以轮询以检查待处理的输入,在特定时间后超时,或无限期等待输入,这使得 select 系统调用极为灵活。
Most GUI Toolkits provide an interface to select; we will discuss the X Intrinsics (“Xt”) library later in this chapter.
大多数图形用户界面工具包都提供了对 select 的接口;我们将在本章后面讨论 X 内部函数库(“Xt”)。
The SELECT System Call
SELECT 系统调用
The select system call accepts 5 arguments:
select 系统调用接受 5 个参数:
int select(int max_fd, fd_set *input, fd_set *output, fd_set *error, struct timeval *timeout);
The max_fd argument specifies the highest numbered file descriptor in the input, output, and error sets.
max_fd 参数指定 input、output 和 error 集合中最高的文件描述符编号。
The input, output, and error arguments specify sets of file descriptors for pending input, output, or error conditions; specify NULL
to disable monitoring for the corresponding condition.
input、output 和 error 参数指定用于待处理输入、输出或错误条件的文件描述符集合;指定 NULL
以禁用对相应条件的监视。
These sets are initialized using three macros:
这些集合使用三个宏进行初始化:
FD_ZERO(&fd_set);
FD_SET(fd, &fd_set);
FD_CLR(fd, &fd_set);
The FD_ZERO macro clears the set entirely.
FD_ZERO 宏清空整个集合。
The FD_SET and FD_CLR macros add and remove a file descriptor from the set, respectively.
FD_SET 和 FD_CLR 宏分别将文件描述符添加到集合中和从集合中移除。
The timeout argument specifies a timeout value which consists of seconds ( timeout.tv_sec) and microseconds ( timeout.tv_usec ).
timeout 参数指定超时值,包括秒数(timeout.tv_sec)和微秒数(timeout.tv_usec)。
To poll one or more file descriptors, set the seconds and microseconds to zero.
要轮询一个或多个文件描述符,请将秒数和微秒数设置为零。
To wait indefinitely specify NULL
for the timeout pointer.
要无限期等待,请为超时指针指定 NULL
。
The select system call returns the number of file descriptors that have a pending condition, or -1 if there was an error.
select 系统调用返回具有待处理条件的文件描述符数量,或者在发生错误时返回 -1。
Using the SELECT System Call
使用 SELECT 系统调用
Suppose we are reading data from a serial port and a socket.
假设我们正在从串行端口和套接字读取数据。
We want to check for input from either file descriptor, but want to notify the user if no data is seen within 10 seconds.
我们希望检查来自任一文件描述符的输入,但如果在 10 秒内没有看到任何数据,则希望通知用户。
To do this we’ll need to use the select system call, as shown in Listing 8.
为此,我们需要使用 select 系统调用,如清单 8 所示。
Listing 8 - Using SELECT to process input from more than one source.
清单 8 - 使用 SELECT 处理来自多个来源的输入。
#include <unistd.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/select.h>
int n;
int socket;
int fd;
int max_fd;
fd_set input;
struct timeval timeout;
/* Initialize the input set */
FD_ZERO(&input);
FD_SET(fd, &input);
FD_SET(sock, &input);
max_fd = (sock > fd ? sock : fd) + 1;
/* Initialize the timeout structure */
timeout.tv_sec = 10;
timeout.tv_usec = 0;
/* Do the select */
n = select(max_fd, &input, NULL, NULL, &timeout);
/* See if there was an error */
if (n < 0)
perror("select failed");
else if (n == 0)
puts("TIMEOUT");
else
{
/* We have input */
if (FD_ISSET(fd, &input))
process_fd();
if (FD_ISSET(sock, &input))
process_socket();
}
You’ll notice that we first check the return value of the select system call.
您会注意到,我们首先检查 select 系统调用的返回值。
Values of 0 and -1 yield the appropriate warning and error messages.
值为 0 和 -1 会生成相应的警告和错误消息。
Values greater than 0 mean that we have data pending on one or more file descriptors.
大于 0 的值意味着我们有一个或多个文件描述符上有待处理的数据。
To determine which file descriptor(s) have pending input, we use the FD_ISSET macro to test the input set for each file descriptor.
要确定哪个文件描述符上有待处理的输入,我们使用 FD_ISSET 宏测试每个文件描述符的输入集合。
If the file descriptor flag is set then the condition exists (input pending in this case) and we need to do something.
如果文件描述符标志已设置,则条件存在(在此情况下为输入待处理),我们需要采取一些措施。
Using SELECT with the X Intrinsics Library
使用 X 内部函数库的 SELECT
The X Intrinsics library provides an interface to the select system call via the XtAppAddInput(3x) and XtAppRemoveInput(3x) functions:
X 内部函数库通过 XtAppAddInput(3x) 和 XtAppRemoveInput(3x) 函数为 select 系统调用提供了一个接口:
int XtAppAddInput(XtAppContext context, int fd, int mask, XtInputProc proc, XtPointer data);
void XtAppRemoveInput(XtAppContext context, int input);
The select system call is used internally to implement timeouts, work procedures, and check for input from the X server.
select 系统调用在内部用于实现超时、工作程序,并检查来自 X 服务器的输入。
These functions can be used with any Xt-based toolkit including Xaw, Lesstif, and Motif.
这些函数可以与任何基于 Xt 的工具包一起使用,包括 Xaw、Lesstif 和 Motif。
The proc argument to XtAppAddInput specifies the function to call when the selected condition (e.g. input available) exists on the file descriptor.
XtAppAddInput 的 proc 参数指定了当文件描述符上存在选定条件(例如,有输入可用)时要调用的函数。
In the previous example you could specify the process_fd or process_socket functions.
在前面的示例中,您可以指定 process_fd 或 process_socket 函数。
Because Xt limits your access to the select system call, you’ll need to implement timeouts through another mechanism, probably via XtAppAddTimeout(3x).
由于 Xt 限制了您对 select 系统调用的访问,您需要通过其他机制实现超时,可能通过 XtAppAddTimeout(3x)。
Appendix A, Pinouts
附录 A,引脚布局
This appendix provides pinout information for many of the common serial ports you will find.
本附录提供了您可能会遇到的许多常见串行端口的引脚布局信息。
RS-232 Pinouts
RS-232 引脚布局
RS-232 comes in three flavors (A, B, C) and uses a 25-pin D-Sub connector:
RS-232 有三种版本(A、B、C),并使用 25 针 D-Sub 连接器:
Figure 2 - RS-232 Connector
图 2 - RS-232 连接器
Pin | Description | Pin | Description |
---|---|---|---|
1 | Earth Ground | 14 | Secondary TXD |
2 | TXD - Transmitted Data | 15 | Transmit Clock |
3 | RXD - Received Data | 16 | Secondary RXD |
4 | RTS - Request To Send | 17 | Receiver Clock |
5 | CTS - Clear To Send | 18 | Unassigned |
6 | DSR - Data Set Ready | 19 | Secondary RTS |
7 | GND - Logic Ground | 20 | DTR - Data Terminal Ready |
8 | DCD - Data Carrier Detect | 21 | Signal Quality Detect |
9 | Reserved | 22 | Ring Detect |
10 | Reserved | 23 | Data Rate Select |
11 | Unassigned | 24 | Transmit Clock |
12 | Secondary DCD | 25 | Unassigned |
13 | Secondary CTS |
表 12 - RS-232 信号
RS-422 Pinouts
RS-422 引脚布局
RS-422 also uses a 25-pin D-Sub connector, but with differential signals:
RS-422 也使用 25 针 D-Sub 连接器,但使用差分信号:
Figure 3 - RS-422 Connector
图 3 - RS-422 连接器
Pin | Description | Pin | Description |
---|---|---|---|
1 | Earth Ground | 14 | TXD+ |
2 | TXD- - Transmitted Data | 15 | Transmit Clock- |
3 | RXD- - Received Data | 16 | RXD+ |
4 | RTS- - Request To Send | 17 | Receiver Clock- |
5 | CTS- - Clear To Send | 18 | Unassigned |
6 | DSR - Data Set Ready | 19 | RTS+ |
7 | GND - Logic Ground | 20 | DTR- - Data Terminal Ready |
8 | DCD- - Data Carrier Detect | 21 | Signal Quality Detect |
9 | Reserved | 22 | Unassigned |
10 | Reserved | 23 | DTR+ |
11 | Unassigned | 24 | Transmit Clock+ |
12 | DCD+ | 25 | Receiver Clock+ |
13 | CTS+ |
表 13 - RS-422 信号
RS-574 (IBM PC/AT) Pinouts
RS-574 (IBM PC/AT) 引脚布局
The RS-574 interface is used exclusively by PC manufacturers and uses a 9-pin male D-Sub connector:
RS-574 接口仅由 PC 制造商使用,采用 9 针公头 D-Sub 连接器:
Figure 4 - RS-574 Connector
图 4 - RS-574 连接器
Pin | Description | Pin | Description |
---|---|---|---|
1 | DCD - Data Carrier Detect | 6 | Data Set Ready |
2 | RXD - Received Data | 7 | RTS - Request To Send |
3 | TXD - Transmitted Data | 8 | CTS - Clear To Send |
4 | DTR - Data Terminal Ready | 9 | Ring Detect |
5 | GND - Logic Ground |
表 14 - RS-574 (IBM PC/AT) 信号
SGI Pinouts
SGI 引脚布局
Older SGI equipment uses a 9-pin female D-Sub connector. Unlike RS-574, the SGI pinouts nearly match those of RS-232:
较旧的 SGI 设备使用 9 针母头 D-Sub 连接器。与 RS-574 不同,SGI 的引脚布局几乎与 RS-232 相同:
Figure 5 - SGI 9-Pin Connector
图 5 - SGI 9 针连接器
Pin | Description | Pin | Description |
---|---|---|---|
1 | Earth Ground | 6 | DSR - Data Set Ready |
2 | TXD - Transmitted Data | 7 | GND - Logic Ground |
3 | RXD - Received Data | 8 | DCD - Data Carrier Detect |
4 | RTS - Request To Send | 9 | DTR - Data Terminal Ready |
5 | CTS - Clear To Send |
表 15 - SGI 9 针 DSUB 信号
The SGI Indigo, Indigo2, and Indy workstations use the Apple 8-pin MiniDIN connector for their serial ports:
SGI Indigo、Indigo2 和 Indy 工作站使用 Apple 8 针 MiniDIN 连接器作为其串行端口:
Figure 6 - SGI 8-Pin Connector
图 6 - SGI 8 针连接器
Pin | Description | Pin | Description |
---|---|---|---|
1 | DTR - Data Terminal Ready | 5 | RXD - Received Data |
2 | CTS - Clear To Send | 6 | RTS - Request To Send |
3 | TXD - Transmitted Data | 7 | DCD - Data Carrier Detect |
4 | GND - Logic Ground | 8 | GND - Logic Ground |
表 16 - SGI 8 针 MiniDIN 信号
Appendix B, ASCII Control Codes
附录 B,ASCII 控制码
This chapter lists the ASCII control codes and their names.
本章列出了 ASCII 控制码及其名称。
Control Codes
控制码
The following ASCII characters are used for control purposes:
以下 ASCII 字符用于控制目的:
Name | Binary | Octal | Decimal | Hexadecimal |
---|---|---|---|---|
NUL | 00000000 | 000 | 0 | 00 |
SOH | 00000001 | 001 | 1 | 01 |
STX | 00000010 | 002 | 2 | 02 |
ETX | 00000011 | 003 | 3 | 03 |
EOT | 00000100 | 004 | 4 | 04 |
ENQ | 00000101 | 005 | 5 | 05 |
ACK | 00000110 | 006 | 6 | 06 |
BEL | 00000111 | 007 | 7 | 07 |
BS | 00001000 | 010 | 8 | 08 |
HT | 00001001 | 011 | 9 | 09 |
NL | 00001010 | 012 | 10 | 0A |
VT | 00001011 | 013 | 11 | 0B |
NP, FF | 00001100 | 014 | 12 | 0C |
CR | 00001101 | 015 | 13 | 0D |
SO | 00001110 | 016 | 14 | 0E |
SI | 00001111 | 017 | 15 | 0F |
DLE | 00010000 | 020 | 16 | 10 |
XON, DC1 | 00010001 | 021 | 17 | 11 |
DC2 | 00010010 | 022 | 18 | 12 |
XOFF, DC3 | 00010011 | 023 | 19 | 13 |
DC4 | 00010100 | 024 | 20 | 14 |
NAK | 00010101 | 025 | 21 | 15 |
SYN | 00010110 | 026 | 22 | 16 |
ETB | 00010111 | 027 | 23 | 17 |
CAN | 00011000 | 030 | 24 | 18 |
EM | 00011001 | 031 | 25 | 19 |
SUB | 00011010 | 032 | 26 | 1A |
ESC | 00011011 | 033 | 27 | 1B |
FS | 00011100 | 034 | 28 | 1C |
GS | 00011101 | 035 | 29 | 1D |
RS | 00011110 | 036 | 30 | 1E |
US | 00011111 | 037 | 31 | 1F |
表 17 - ASCII 控制码
Appendix C, GNU Free Documentation License
附录 C,GNU 自由文档许可证
Version 1.2, November 2002
版本 1.2,2002 年 11 月
Copyright (C) 2000,2001,2002 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
0. PREAMBLE
0. 前言
The purpose of this License is to make a manual, textbook, or other functional and useful document “free” in the sense of freedom: to assure everyone the effective freedom to copy and redistribute it, with or without modifying it, either commercially or noncommercially.
本许可证的目的是使手册、教科书或其他功能性和有用的文档在自由的意义上是“自由的”:确保每个人都有有效的自由复制和再分发它,无论是否修改,无论是商业用途还是非商业用途。
Secondarily, this License preserves for the author and publisher a way to get credit for their work, while not being considered responsible for modifications made by others.
其次,本许可证为作者和出版商保留了一种获得其作品认可的方式,同时不被视为对他人所做的修改负责。
This License is a kind of “copyleft”, which means that derivative works of the document must themselves be free in the same sense.
本许可证是一种“著佐权”,这意味着文档的衍生作品本身必须在相同的意义上是自由的。
It complements the GNU General Public License, which is a copyleft license designed for free software.
它补充了 GNU 通用公共许可证,该许可证是为自由软件设计的著佐权许可证。
We have designed this License in order to use it for manuals for free software, because free software needs free documentation: a free program should come with manuals providing the same freedoms that the software does.
我们设计本许可证是为了将其用于自由软件的手册,因为自由软件需要自由的文档:一个自由程序应该附带提供与软件相同的自由的手册。
But this License is not limited to software manuals; it can be used for any textual work, regardless of subject matter or whether it is published as a printed book.
但本许可证不限于软件手册;它可以用于任何文本作品,无论主题如何,也无论其是否以印刷书籍的形式出版。
We recommend this License principally for works whose purpose is instruction or reference.
我们主要推荐本许可证用于以教学或参考为目的的作品。
1. APPLICABILITY AND DEFINITIONS
1. 适用性和定义
This License applies to any manual or other work, in any medium, that contains a notice placed by the copyright holder saying it can be distributed under the terms of this License.
本许可证适用于任何媒介中的任何手册或其他作品,只要该作品包含版权所有者放置的通知,声明其可以根据本许可证的条款进行分发。
Such a notice grants a world-wide, royalty-free license, unlimited in duration, to use that work under the conditions stated herein.
此类通知授予一个全球性的、免版税的许可证,期限不受限制,允许在本许可证规定的条件下使用该作品。
The “Document”, below, refers to any such manual or work.
下面的“文档”指的是任何这样的手册或作品。
Any member of the public is a licensee, and is addressed as “you”.
任何公众成员都是被许可人,被称为“您”。
You accept the license if you copy, modify or distribute the work in a way requiring permission under copyright law.
如果您以需要版权法许可的方式复制、修改或分发该作品,则您接受该许可证。
A “Modified Version” of the Document means any work containing the Document or a portion of it, either copied verbatim, or with modifications and/or translated into another language.
“文档的修改版本”是指包含文档或其部分内容的任何作品,无论是逐字复制的,还是经过修改和/或翻译成其他语言的。
A “Secondary Section” is a named appendix or a front-matter section of the Document that deals exclusively with the relationship of the publishers or authors of the Document to the Document’s overall subject (or to related matters) and contains nothing that could fall directly within that overall subject.
“次要部分”是指文档中专门处理文档出版者或作者与文档整体主题(或相关事项)之间关系的附录或前言部分,并且不包含任何直接属于该整体主题的内容。
The “Invariant Sections” are certain Secondary Sections whose titles are designated, as being those of Invariant Sections, in the notice that says that the Document is released under this License.
“不变部分”是指在声明文档根据本许可证发布的通知中指定标题的某些次要部分。
If a section does not fit the above definition of Secondary then it is not allowed to be designated as Invariant.
如果一个部分不符合上述次要部分的定义,则不允许将其指定为不变部分。
The Document may contain zero Invariant Sections.
文档可以包含零个不变部分。
If the Document does not identify any Invariant Sections then there are none.
如果文档没有标识任何不变部分,则不存在不变部分。
The “Cover Texts” are certain short passages of text that are listed, as Front-Cover Texts or Back-Cover Texts, in the notice that says that the Document is released under this License.
“封面文字”是指在声明文档根据本许可证发布的通知中列出的某些简短文字,作为前封面文字或后封面文字。
A Front-Cover Text may be at most 5 words, and a Back-Cover Text may be at most 25 words.
前封面文字最多可以有 5 个单词,后封面文字最多可以有 25 个单词。
2. VERBATIM COPYING
2. 逐字复制
You may copy and distribute the Document in any medium, either commercially or noncommercially, provided that this License, the copyright notices, and the license notice saying this License applies to the Document are reproduced in all copies, and that you add no other conditions whatsoever to those of this License.
您可以在任何媒介中复制和分发该文档,无论是商业用途还是非商业用途,只要在所有副本中复制了本许可证、版权声明以及声明本许可证适用于该文档的许可证通知,并且您没有向本许可证的条件添加任何其他条件。
You may not use technical measures to obstruct or control the reading or further copying of the copies you make or distribute.
您不得使用技术手段阻碍或控制您制作或分发的副本的阅读或进一步复制。
However, you may accept compensation in exchange for copies.
然而,您可以接受以副本交换的补偿。
If you distribute a large enough number of copies you must also follow the conditions in section 3.
如果您分发了足够多的副本,您还必须遵守第 3 节中的条件。
3. COPYING IN QUANTITY
3. 大量复制
If you publish printed copies (or copies in media that commonly have printed covers) of the Document, numbering more than 100, and the Document’s license notice requires Cover Texts, you must enclose the copies in covers that carry, clearly and legibly, all these Cover Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on the back cover.
如果出版的文档副本(或通常有印刷封面的媒体副本)数量超过 100 份,并且文档的许可证通知要求有封面文字,则必须将副本装入封面,封面必须清晰且醒目地印有所有这些封面文字:前封面文字印在前面,后封面文字印在后面。
Both covers must also clearly and legibly identify you as the publisher of these copies.
两个封面还必须清楚且醒目地标识您为这些副本的出版商。
The front cover must present the full title with all words of the title equally prominent and visible.
前封面必须以所有标题词同等突出和可见的方式呈现完整标题。
You may add other material on the covers in addition.
您可以在封面上添加其他材料。
Copying with changes limited to the covers, as long as they preserve the title of the Document and satisfy these conditions, can be treated as verbatim copying in other respects.
只要封面的更改保留了文档的标题并满足这些条件,就可以在其他方面被视为逐字复制。
If the required texts for either cover are too voluminous to fit legibly, you should put the first ones listed (as many as fit reasonably) on the actual cover, and continue the rest onto adjacent pages.
如果封面所需的文本过于冗长,无法清晰地印在封面上,则应将列出的前几条(尽可能多地)印在实际封面上,并将剩余部分继续印在相邻页面上。
If you publish or distribute Opaque copies of the Document numbering more than 100, you must either include a machine-readable Transparent copy along with each Opaque copy, or state in or with each Opaque copy a computer-network location from which the general network-using public has access to download using public-standard network protocols a complete Transparent copy of the Document, free of added material.
如果您出版或分发的文档不透明副本数量超过 100 份,则必须在每个不透明副本中附带一份机器可读的透明副本,或者在每个不透明副本中或随附说明中提供一个计算机网络位置,以便一般网络用户可以使用公共标准网络协议下载完整的透明副本,且不包含任何添加的材料。
If you use the latter option, you must take reasonably prudent steps, when you begin distribution of Opaque copies in quantity, to ensure that this Transparent copy will remain thus accessible at the stated location until at least one year after the last time you distribute an Opaque copy (directly or through your agents or retailers) of that edition to the public.
如果您选择后一种选项,则在开始大量分发不透明副本时,您必须采取合理的谨慎措施,以确保该透明副本在声明的位置上保持可访问,直到您最后一次向公众分发该版本的不透明副本(直接或通过您的代理人或零售商)后至少一年。
It is requested, but not required, that you contact the authors of the Document well before redistributing any large number of copies, to give them a chance to provide you with an updated version of the Document.
建议(但不是强制要求)您在重新分发大量副本之前与文档的作者联系,以便他们有机会为您提供文档的更新版本。
4. MODIFICATIONS
4. 修改
You may copy and distribute a Modified Version of the Document under the conditions of sections 2 and 3 above, provided that you release the Modified Version under precisely this License, with the Modified Version filling the role of the Document, thus licensing distribution and modification of the Modified Version to whoever possesses a copy of it.
您可以在上述第 2 节和第 3 节的条件下复制和分发文档的修改版本,只要您在完全相同的许可证下发布修改版本,使修改版本充当文档的角色,从而允许任何拥有其副本的人分发和修改修改版本。
In addition, you must do these things in the Modified Version:
此外,您必须在修改版本中做以下事情:
-
A. Use in the Title Page (and on the covers, if any) a title distinct from that of the Document, and from those of previous versions (which should, if there were any, be listed in the History section of the Document). You may use the same title as a previous version if the original publisher of that version gives permission.
A. 在标题页(以及封面上,如果有)使用与文档以及以前版本(如果有的话,应在文档的历史部分列出)不同的标题。如果以前版本的原始出版商允许,您可以使用与以前版本相同的标题。 -
B. List on the Title Page, as authors, one or more persons or entities responsible for authorship of the modifications in the Modified Version, together with at least five of the principal authors of the Document (all of its principal authors, if it has fewer than five), unless they release you from this requirement.
B. 在标题页上,作为作者,列出对修改版本中的修改负责的一人或多个人或实体,以及文档的主要作者中的至少五位(如果文档的主要作者少于五位,则列出所有主要作者),除非他们免除您的这一要求。 -
C. State on the Title page the name of the publisher of the Modified Version, as the publisher.
C. 在标题页上标明修改版本的出版商名称,作为出版商。 -
D. Preserve all the copyright notices of the Document.
D. 保留文档的所有版权声明。 -
E. Add an appropriate copyright notice for your modifications adjacent to the other copyright notices.
E. 在其他版权声明旁边添加您修改的适当版权声明。 -
F. Include, immediately after the copyright notices, a license notice giving the public permission to use the Modified Version under the terms of this License, in the form shown in the Addendum below.
F. 在版权声明之后,包括一个许可证通知,允许公众在本许可证的条款下使用修改版本,形式如下面的附录所示。 -
G. Preserve in that license notice the full lists of Invariant Sections and required Cover Texts given in the Document’s license notice.
G. 在该许可证通知中保留文档许可证通知中给出的不变部分和所需封面文字的完整列表。 -
H. Include an unaltered copy of this License.
H. 包括一份未修改的本许可证副本。 -
I. Preserve the section Entitled “History”, Preserve its Title, and add to it an item stating at least the title, year, new authors, and publisher of the Modified Version as given on the Title Page. If there is no section Entitled “History” in the Document, create one stating the title, year, authors, and publisher of the Document as given on its Title Page, then add an item describing the Modified Version as stated in the previous sentence.
I. 保留标题为“历史”的部分,保留其标题,并添加一项,至少说明修改版本的标题、年份、新作者和出版商,如标题页所示。如果文档中没有标题为“历史”的部分,则创建一个,说明文档的标题、年份、作者和出版商,如其标题页所示,然后添加一项,描述修改版本,如前一句所述。 -
J. Preserve the network location, if any, given in the Document for public access to a Transparent copy of the Document, and likewise the network locations given in the Document for previous versions it was based on. These may be placed in the “History” section. You may omit a network location for a work that was published at least four years before the Document itself, or if the original publisher of the version it refers to gives permission.
J. 保留文档中给出的用于公众访问文档透明副本的网络位置(如果有),以及文档中给出的用于其基于的以前版本的网络位置。这些可以放在“历史”部分。如果该作品在文档本身发布前至少四年出版,或者如果其引用的版本的原始出版商给予许可,您可以省略网络位置。 -
K. For any section Entitled “Acknowledgements” or “Dedications”, Preserve the Title of the section, and preserve in the section all the substance and tone of each of the contributor acknowledgements and/or dedications given therein.
K. 对于标题为“致谢”或“献辞”的任何部分,保留该部分的标题,并保留该部分中每个贡献者的致谢和/或献辞的内容和语气。 -
L. Preserve all the Invariant Sections of the Document, unaltered in their text and in their titles. Section numbers or the equivalent are not considered part of the section titles.
L. 保留文档的所有不变部分,其文本和标题均不得更改。节号或等价物不被视为节标题的一部分。 -
M. Delete any section Entitled “Endorsements”. Such a section may not be included in the Modified Version.
M. 删除任何标题为“认可”的部分。修改版本中不得包含此类部分。 -
N. Do not retitle any existing section to be Entitled “Endorsements” or to conflict in title with any Invariant Section.
N. 不要将任何现有部分重新命名为“认可”,或与任何不变部分的标题冲突。 -
O. Preserve any Warranty Disclaimers.
O. 保留任何保证免责声明。
If the Modified Version includes new front-matter sections or appendices that qualify as Secondary Sections and contain no material copied from the Document, you may at your option designate some or all of these sections as invariant. To do this, add their titles to the list of Invariant Sections in the Modified Version’s license notice. These titles must be distinct from any other section titles.
如果修改版本包含新的前言部分或附录,这些部分符合次要部分的资格,并且不包含从文档中复制的任何材料,则您可以选择将这些部分中的某些或全部指定为不变部分。为此,将它们的标题添加到修改版本许可证通知中的不变部分列表中。这些标题必须与其他任何部分标题不同。
You may add a section Entitled “Endorsements”, provided it contains nothing but endorsements of your Modified Version by various parties - for example, statements of peer review or that the text has been approved by an organization as the authoritative definition of a standard.
您可以添加一个标题为“认可”的部分,条件是它只包含各方对您的修改版本的认可 - 例如,同行评审的声明,或者文本已被某个组织批准为某个标准的权威定义。
You may add a passage of up to five words as a Front-Cover Text, and a passage of up to 25 words as a Back-Cover Text, to the end of the list of Cover Texts in the Modified Version. Only one passage of Front-Cover Text and one of Back-Cover Text may be added by (or through arrangements made by) any one entity. If the Document already includes a cover text for the same cover, previously added by you or by arrangement made by the same entity you are acting on behalf of, you may not add another; but you may replace the old one, on explicit permission from the previous publisher that added the old one.
您可以将最多五个单词的段落作为前封面文字,以及最多 25 个单词的段落作为后封面文字,添加到修改版本的封面文字列表的末尾。任何实体(或通过该实体安排)只能添加一段前封面文字和一段后封面文字。如果文档已经包含了您或代表同一实体添加的相同封面的封面文字,则您不能添加另一段;但您可以替换旧的那一段,前提是获得添加旧封面文字的出版商的明确许可。
The author(s) and publisher(s) of the Document do not by this License give permission to use their names for publicity for or to assert or imply endorsement of any Modified Version.
本许可证并不授予使用文档作者或出版商的姓名进行宣传,或声称或暗示对任何修改版本的认可。
5. COMBINING DOCUMENTS
5. 合并文档
You may combine the Document with other documents released under this License, under the terms defined in section 4 above for modified versions, provided that you include in the combination all of the Invariant Sections of all of the original documents, unmodified, and list them all as Invariant Sections of your combined work in its license notice, and that you preserve all their Warranty Disclaimers.
您可以根据上述第 4 节中为修改版本定义的条款,将文档与其他在本许可证下发布的文档合并,条件是您在合并文档中包含所有原始文档的所有不变部分(未经修改),并将它们全部列为合并作品许可证通知中的不变部分,同时保留所有这些保证免责声明。
The combined work need only contain one copy of this License, and multiple identical Invariant Sections may be replaced with a single copy.
合并作品只需包含一份本许可证副本,多个相同的不变部分可以用一份副本替换。
If there are multiple Invariant Sections with the same name but different contents, make the title of each such section unique by adding at the end of it, in parentheses, the name of the original author or publisher of that section if known, or else a unique number.
如果存在多个名称相同但内容不同的不变部分,请在每个部分的末尾加上括号,注明该部分的原始作者或出版商的名称(如果已知),或者使用一个唯一的数字。
Make the same adjustment to the section titles in the list of Invariant Sections in the license notice of the combined work.
对合并作品许可证通知中不变部分的列表中的部分标题进行相同的调整。
In the combination, you must combine any sections Entitled “History” in the various original documents, forming one section Entitled “History”; likewise combine any sections Entitled “Acknowledgements”, and any sections Entitled “Dedications”. You must delete all sections Entitled “Endorsements.”
在合并文档时,您必须将各个原始文档中标题为“历史”的部分合并为一个标题为“历史”的部分;同样,合并所有标题为“致谢”的部分以及所有标题为“献辞”的部分。您必须删除所有标题为“认可”的部分。
6. COLLECTIONS OF DOCUMENTS
6. 文档集合
You may make a collection consisting of the Document and other documents released under this License, and replace the individual copies of this License in the various documents with a single copy that is included in the collection, provided that you follow the rules of this License for verbatim copying of each of the documents in all other respects.
您可以制作一个包含文档和其他在本许可证下发布的文档的集合,并用包含在集合中的单一副本替换各个文档中的本许可证副本,前提是您遵循本许可证的规则,逐字复制每个文档的所有其他方面。
You may extract a single document from such a collection, and distribute it individually under this License, provided you insert a copy of this License into the extracted document, and follow this License in all other respects regarding verbatim copying of that document.
您可以从这样的集合中提取一个单独的文档,并在本许可证下单独分发,前提是您将本许可证副本插入到提取的文档中,并遵循本许可证的所有其他方面,关于该文档的逐字复制。
7. AGGREGATION WITH INDEPENDENT WORKS
7. 与独立作品的聚合
A compilation of the Document or its derivatives with other separate and independent documents or works, in or on a volume of a storage or distribution medium, is called an “aggregate” if the copyright resulting from the compilation is not used to limit the legal rights of the compilation’s users beyond what the individual works permit.
如果由于编译而产生的版权不被用于限制编译用户的合法权利,超出各个作品所允许的范围,则将文档或其衍生作品与其他独立的文档或作品在存储或分发介质的卷中编译在一起,称为“聚合”。
When the Document is included in an aggregate, this License does not apply to the other works in the aggregate which are not themselves derivative works of the Document.
当文档包含在聚合中时,本许可证不适用于聚合中的其他作品,这些作品本身并非文档的衍生作品。
If the Cover Text requirement of section 3 is applicable to these copies of the Document, then if the Document is less than one half of the entire aggregate, the Document’s Cover Texts may be placed on covers that bracket the Document within the aggregate, or the electronic equivalent of covers if the Document is in electronic form.
如果第 3 节的封面文字要求适用于这些文档副本,则如果文档少于整个聚合的一半,文档的封面文字可以放在括起聚合中文档的封面上,或者如果文档是电子形式,则可以放在封面的电子等价物上。
Otherwise they must appear on printed covers that bracket the whole aggregate.
否则,它们必须出现在括起整个聚合的印刷封面上。
8. TRANSLATION
8. 翻译
Translation is considered a kind of modification, so you may distribute translations of the Document under the terms of section 4.
翻译被视为一种修改,因此您可以根据第 4 节的条款分发文档的翻译版本。
Replacing Invariant Sections with translations requires special permission from their copyright holders, but you may include translations of some or all Invariant Sections in addition to the original versions of these Invariant Sections.
用翻译替换不变部分需要获得其版权所有者的特别许可,但您可以包括一些或所有不变部分的翻译,以及这些不变部分的原始版本。
You may include a translation of this License, and all the license notices in the Document, and any Warranty Disclaimers, provided that you also include the original English version of this License and the original versions of those notices and disclaimers. In case of a disagreement between the translation and the original version of this License or a notice or disclaimer, the original version will prevail.
您可以包括本许可证的翻译版本,以及文档中的所有许可证通知和任何保证免责声明,前提是您还包含本许可证的原始英文版本以及这些通知和免责声明的原始版本。如果翻译版本与本许可证或通知或免责声明的原始版本之间存在分歧,原始版本将占优势。
If a section in the Document is Entitled “Acknowledgements”, “Dedications”, or “History”, the requirement (section 4) to Preserve its Title (section 1) will typically require changing the actual title.
如果文档中的一个部分标题为“致谢”、“献辞”或“历史”,则第 4 节中保留其标题的要求(第 1 节)通常需要更改实际标题。
9. TERMINATION
9. 终止
You may not copy, modify, sublicense, or distribute the Document except as expressly provided for under this License. Any other attempt to copy, modify, sublicense or distribute the Document is void, and will automatically terminate your rights under this License.
您不得复制、修改、再授权或分发文档,除非本许可证明确允许。任何其他尝试复制、修改、再授权或分发文档的行为都是无效的,并将自动终止您在本许可证下的权利。
However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance.
然而,只要这些当事人完全遵守本许可证,从您那里根据本许可证获得副本或权利的当事人不会终止他们的许可证。
10. FUTURE REVISIONS OF THIS LICENSE
10. 本许可证的未来修订版本
The Free Software Foundation may publish new, revised versions of the GNU Free Documentation License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. See http://www.gnu.org/copyleft/.
自由软件基金会可能会不时发布 GNU 自由文档许可证的新版本。这些新版本将在精神上与当前版本相似,但可能会在细节上有所不同,以解决新问题或关注点。请参阅 http://www.gnu.org/copyleft/。
Each version of the License is given a distinguishing version number. If the Document specifies that a particular numbered version of this License “or any later version” applies to it, you have the option of following the terms and conditions either of that specified version or of any later version that has been published (not as a draft) by the Free Software Foundation. If the Document does not specify a version number of this License, you may choose any version ever published (not as a draft) by the Free Software Foundation.
每个许可证版本都有一个区分的版本号。如果文档指定了本许可证的某个编号版本“或任何后续版本”适用于它,您可以选择遵循该指定版本的条款和条件,或者遵循自由软件基金会已发布(不是作为草案)的任何后续版本的条款和条件。如果文档没有指定本许可证的版本号,您可以选择自由软件基金会曾经发布(不是作为草案)的任何版本。
How to use this License for your documents
如何为您的文档使用此许可证
To use this License in a document you have written, include a copy of the License in the document and put the following copyright and license notices just after the title page:
要在您撰写的文档中使用此许可证,请在文档中包含一份许可证副本,并在标题页之后放置以下版权声明和许可证通知:
Copyright © YEAR YOUR NAME.
Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.2 or any later version published by the Free Software Foundation;
with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A copy of the license is included in the section entitled “GNU Free Documentation License”.
If you have Invariant Sections, Front-Cover Texts and Back-Cover Texts, replace the “with…Texts.” line with this:
如果您有不变部分、前封面文字和后封面文字,请将“with…Texts.”行替换为以下内容:
with the Invariant Sections being LIST THEIR TITLES, with the Front-Cover Texts being LIST, and with the Back-Cover Texts being LIST.
If you have Invariant Sections without Cover Texts, or some other combination of the three, merge those two alternatives to suit the situation.
如果您有不变部分但没有封面文字,或者这三者的其他组合,请根据实际情况合并这两种选择。
If your document contains nontrivial examples of program code, we recommend releasing these examples in parallel under your choice of free software license, such as the GNU General Public License, to permit their use in free software.
如果您的文档包含非平凡的程序代码示例,我们建议您根据您的选择的自由软件许可证(例如 GNU 通用公共许可证)同时发布这些示例,以允许它们在自由软件中使用。
Appendix D, Change History
附录 D,变更历史
This appendix lists the changes that have been made in this edition.
本附录列出了本版本中所做的更改。
Edition 5, Revision 6
第五版,第六次修订
The following changes were made for the 6th revision:
第六次修订所做的更改如下:
-
The select() example did not correctly use the FD macros.
select() 示例未正确使用 FD 宏。 -
The title page and this appendix were not properly updated.
标题页和本附录未正确更新。
Edition 5, Revision 5
第五版,第五次修订
The following changes were made for the 5th revision:
第五次修订所做的更改如下:
-
The select() documentation did not correctly describe the FD macros.
select() 文档未正确描述 FD 宏。 -
Appendix C was missing the “how to use” part of the GNU FDL.
附录 C 缺少 GNU FDL 的“如何使用”部分。
Edition 5, Revision 4
第五版,第四次修订
The following changes were made for the 4th revision:
第四次修订所做的更改如下:
-
Changed the description of the read() system call semantics in chapter 1.
修改了第 1 章中对 read() 系统调用语义的描述。 -
Added descriptions for VSTART and VSTOP to chapter 2.
在第 2 章中添加了对 VSTART 和 VSTOP 的描述。
Edition 5, Revision 3
第五版,第三次修订
The following changes were made for the 3rd revision:
第三次修订所做的更改如下:
-
Now use the GNU Free Documentation License for the guide.
现在使用 GNU 自由文档许可证为本指南。 -
Changed the examples to use the Linux serial port filenames.
将示例改为使用 Linux 串行端口文件名。 -
Put the infrastructure in place to allow for easier translations of the guide.
建立了基础设施,以便于指南的翻译。 -
The guide text is now fully justified.
指南文本现在已完全对齐。
via:
- Serial Programming Guide for POSIX Operating Systems
https://www.msweet.org/serial/serial.html