linux中tty、pty、/dev/ttySn等概念讲解

本文介绍了Linux系统中的各类终端设备,包括tty(终端设备)、pty(伪终端)、pts/ptmx(虚拟终端实现方法)、串行端口终端、控制终端、控制台终端及虚拟终端等,并解释了它们之间的联系和区别。

基本概念:

1》tty(终端设备的统称):

tty一词源于Teletypes,或者teletypewriters,原来指的是电传打字机,是通过串行线用打印机键盘通过阅读和发送信息的东西,后来这东西被键盘与显示器取代,所以现在叫终端比较合适。

终端是一种字符型设备,它有多种类型,通常使用tty来简称各种类型的终端设备。

2》pty(伪终端,虚拟终端):

但是如果我们远程telnet到主机或使用xterm时不也需要一个终端交互么?是的,这就是虚拟终端pty(pseudo-tty)

3》pts/ptmx(pts/ptmx结合使用,进而实现pty):

pts(pseudo-terminal slave)是pty的实现方法,与ptmx(pseudo-terminal master)配合使用实现pty。

在Linux系统的设备特殊文件目录/dev/下,终端特殊设备文件一般有以下几种:

1、串行端口终端(/dev/ttySn)

串行端口终端(Serial Port Terminal)是使用计算机串行端口连接的终端设备。计算机把每个串行端口都看作是一个字符设备。有段时间这些串行端口设备通常被称为终端设备,因为那时它的最大用途就是用来连接终端。这些串行端口所对应的设备名称是/dev/tts/0(或/dev/ttyS0), /dev/tts/1(或/dev/ttyS1)等,设备号分别是(4,0), (4,1)等,分别对应于DOS系统下的COM1、COM2等。若要向一个端口发送数据,可以在命令行上把标准输出重定向到这些特殊文件名上即可。例如,在命令行提示符下键入:echo test 》 /dev/ttyS1会把单词”test”发送到连接在ttyS1(COM2)端口的设备上。

2、伪终端(/dev/pty/)

伪终端(Pseudo Terminal)是成对的逻辑终端设备(即master和slave设备, 对master的操作会反映到slave上)。

例如/dev/ptyp3和/dev/ttyp3(或者在设备文件系统中分别是/dev/pty /m3和 /dev/pty/s3)。它们与实际物理设备并不直接相关。如果一个程序把ptyp3(master设备)看作是一个串行端口设备,则它对该端口的读/ 写操作会反映在该逻辑终端设备对应的另一个ttyp3(slave设备)上面。而ttyp3则是另一个程序用于读写操作的逻辑设备。telnet主机A就是通过“伪终端”与主机A的登录程序进行通信。

3、控制终端(/dev/tty)

如果当前进程有控制终端(Controlling Terminal)的话,那么/dev/tty就是当前进程的控制终端的设备特殊文件。可以使用命令”ps –ax”来查看进程与哪个控制终端相连。对于你登录的shell,/dev/tty就是你使用的终端,设备号是(5,0)。使用命令”tty”可以查看它具体对应哪个实际终端设备。/dev/tty有些类似于到实际所使用终端设备的一个联接。

4、控制台终端(/dev/ttyn, /dev/console)

在Linux 系统中,计算机显示器通常被称为控制台终端 (Console)。它仿真了类型为Linux的一种终端(TERM=Linux),并且有一些设备特殊文件与之相关联:tty0、tty1、tty2 等。当你在控制台上登录时,使用的是tty1。使用Alt+[F1—F6]组合键时,我们就可以切换到tty2、tty3等上面去。tty1–tty6等称为虚拟终端,而tty0则是当前所使用虚拟终端的一个别名,系统所产生的信息会发送到该终端上(这时也叫控制台终端)。因此不管当前正在使用哪个虚拟终端,系统信息都会发送到控制台终端上。/dev/console即控制台,是与操作系统交互的设备,系统将一些信息直接输出到控制台上。目前只有在单用户模式下,才允许用户登录控制台。

5 虚拟终端(/dev/pts/n)

在Xwindows模式下的伪终端。如我在Kubuntu下用konsole,就是用的虚拟终端,用tty命令可看到/dev/pts/1。

6 其它类型

Linux系统中还针对很多不同的字符设备存在有很多其它种类的终端设备特殊文件。例如针对ISDN设备的/dev/ttyIn终端设备等。这里不再赘述。

tty设备包括

虚拟控制台,串口以及伪终端设备。

/dev/tty代表当前tty设备,在当前的终端中输入 echo “hello” 》 /dev/tty ,都会直接显示在当前的终端中。

<think> 我们面对的问题:Python程序尝试打开串口设备`/dev/ttyACM0`失败,错误信息为`[Errno 2] No such file or directory`。 用户已经执行了`ls /dev/tty*`命令,我们需要根据列出的设备信息来查找可用的串口设备,并解决串口打开问题。 解决思路: 1. 确认当前系统实际存在的串口设备(通过用户提供的`/dev/tty*`列表)。 2. 判断`/dev/ttyACM0`不存在的原因(设备未连接?驱动问题?设备节点名称不同?)。 3. 在Python程序中修改代码,连接到实际存在的串口设备。 假设用户提供的`/dev/tty*`设备列表如下(我们需要用户提供,但用户没有在问题中直接给出,因此我们需要假设常见的设备节点,并指导用户自行检查): 常见的串口设备节点包括: - `/dev/ttyS*`:主板内置串口 - `/dev/ttyUSB*`:USB转串口设备(如PL2303、CH340、CP2102等芯片) - `/dev/ttyACM*`:ACM类设备(如Arduino、STM32虚拟串口等) 但是用户遇到了`/dev/ttyACM0`不存在的错误,可能的原因有: - 设备没有正确连接或未被系统识别 - 设备被识别为其他名称(如`/dev/ttyUSB0`) 因此,我们需要用户提供执行`ls /dev/tty*`的具体输出。然而,用户在上一个问题中没有给出输出,所以我们需要引导用户先执行这个命令。 不过,由于当前问题要求我们“结合列出的/dev/tty*设备信息”,但用户并没有在问题中列出,我们只能根据常规情况给出建议: 步骤1:检查设备连接状态 - 确保设备已经通过USB线连接到电脑,并且设备已经上电。 - 重新插拔设备,观察系统是否生成设备节点。 步骤2:再次列出设备,寻找类似`/dev/ttyACM0`或`/dev/ttyUSB0`的设备 - 在终端执行:`ls /dev/tty*` 步骤3:根据实际列出的设备节点修改Python代码 - 如果发现设备节点是`/dev/ttyUSB0`,则将代码中的`'/dev/ttyACM0'`改为`'/dev/ttyUSB0'`。 步骤4:动态选择串口设备(推荐) - 编写代码自动列出可用的串口设备,并选择第一个可用的设备(注意:如果有多个设备,可能需要更精确的识别)。 步骤5:检查权限问题(虽然当前错误是文件不存在,但解决之后可能会遇到权限问题) - 按照之前提供的权限解决方案,将用户加入`dialout`组,并设置正确的udev规则。 由于用户没有提供具体的设备列表,我们只能给出通用步骤。但为了回答的完整性,我们假设用户执行`ls /dev/tty*`后可能看到如下输出: ``` /dev/tty /dev/tty23 /dev/tty39 /dev/tty54 /dev/ttyS0 /dev/tty0 /dev/tty24 /dev/tty4 /dev/tty55 /dev/ttyS1 /dev/tty1 /dev/tty25 /dev/tty40 /dev/tty56 /dev/ttyUSB0 /dev/tty10 /dev/tty26 /dev/tty41 /dev/tty57 ...(省略)... ``` 在这个假设的输出中,我们看到了`/dev/ttyUSB0`,而没有`/dev/ttyACM0`,因此可以判断设备被识别为`/dev/ttyUSB0`。 那么,修改Python程序中的串口设备路径: ```python # 原代码 ser = serial.Serial('/dev/ttyACM0', 115200) # 修改为 ser = serial.Serial('/dev/ttyUSB0', 115200) ``` 如果用户希望代码更加健壮,可以编写自动检测串口设备的代码: 示例代码: ```python import serial.tools.list_ports # 获取所有串口设备列表 ports = list(serial.tools.list_ports.comports()) if len(ports) == 0: print("没有找到任何串口设备!") else: # 假设我们使用第一个找到的串口设备 port = ports[0].device print(f"尝试打开串口: {port}") ser = serial.Serial(port, 115200) ``` 但是,自动选择第一个串口设备可能并不总是正确,因为系统可能有多个串口设备(例如蓝牙模块、GPS模块等)。 更可靠的方法是筛选特定属性的设备(例如通过设备描述、制造商信息等)。 例如,如果我们知道设备的供应商ID和产品ID,可以这样筛选: ```python import serial.tools.list_ports # 定义目标设备的VID和PID(例如Arduino Uno的VID为0x2341,PID为0x0043) TARGET_VID = "2341" TARGET_PID = "0043" # 获取所有串口设备 ports = serial.tools.list_ports.comports() target_port = None for port in ports: # 如果设备信息中包含该VID和PID(注意:不同系统返回的字符串格式可能不同) if TARGET_VID.lower() in port.hwid.lower() and TARGET_PID.lower() in port.hwid.lower(): target_port = port.device break if target_port is None: print("未找到目标设备") else: print(f"找到目标设备:{target_port}") ser = serial.Serial(target_port, 115200) ``` 注意:VID和PID需要根据实际设备在系统中显示的信息进行修改。 另外,如果用户在重新插拔设备后仍然看不到串口设备,可能是驱动问题。例如,使用CH340芯片的设备在较新的Linux内核中可能需要额外安装驱动。但这种情况相对少见。 总结步骤: 1. 确保设备已正确连接并通电。 2. 在终端运行`ls /dev/tty*`,查看可用的串口设备节点。 3. 如果没有`/dev/ttyACM0`,注意是否有`/dev/ttyUSB0`等设备。 4. 根据实际设备节点修改Python程序中的串口设备路径。 5. 如果修改后出现权限问题(Permission denied),则按照之前提供的权限解决方案处理(将用户加入dialout组,设置udev规则等)。 6. 建议改进Python代码,实现自动检测串口设备,避免硬编码设备路径。 注意:以上步骤假设用户的设备被识别为`/dev/ttyUSB0`,但实际情况可能不同,请根据`ls /dev/tty*`的实际输出调整。 如果用户执行`ls /dev/tty*`后仍然没有看到任何类似`ttyACM0`或`ttyUSB0`的设备,则可能是设备未被系统识别,需要检查驱动或硬件连接问题。 最后,生成相关问题: </think> ### 解决串口 /dev/ttyACM0 打开失败问题 针对 Python 程序无法打开 `/dev/ttyACM0` 的问题(错误提示 `[Errno 2] No such file or directory`),以下是系统化的解决方案: --- #### 🔍 步骤 1:确认可用串口设备 在终端执行以下命令,列出所有串口设备: ```bash ls /dev/tty* ``` 观察输出结果(可能出现如下情况): - 如果显示 **`/dev/ttyUSB0`**:表明设备使用 USB 转串口芯片(如 CH340/CP2102) - 如果显示 **`/dev/ttyS0`**:主板原生串口(通常不适合开发板) - **无任何 ACM/USB 设备**:硬件未识别(进入步骤 2) --- #### 🔧 步骤 2:硬件识别问题处理 ##### 情况 A:有 `/dev/ttyUSB0` 设备 修改 Python 代码中的串口路径: ```python # 原代码(问题行) ser = serial.Serial('/dev/ttyACM0', 115200) # 修改为 ser = serial.Serial('/dev/ttyUSB0', 115200) # 使用检测到的 USB 设备 ``` ##### 情况 B:无任何串口设备 1. **物理检查**: - 重新插拔 USB 线(更换 USB 端口) - 确认开发板电源指示灯亮起 - 检查 USB 数据线是否支持数据传输 2. **驱动诊断**: ```bash # 查看内核识别日志 dmesg | grep tty ``` 若输出包含: - `pl2303` 或 `ch341`:需安装驱动 `sudo apt install linux-modules-extra-$(uname -r)` - 无输出:设备未通电或硬件故障 --- #### ⚙ 步骤 3:代码增强(推荐) 添加动态设备检测逻辑避免硬编码路径错误: ```python import serial.tools.list_ports # 获取所有可用串口 available_ports = [p.device for p in serial.tools.list_ports.comports()] print("检测到串口设备:", available_ports) if not available_ports: raise Exception("错误:未检测到任何串口设备") # 自动选择第一个可用端口 target_port = available_ports[0] ser = serial.Serial(target_port, 115200, timeout=1) print(f"成功连接串口:{target_port}") ``` --- #### 🔑 步骤 4:权限问题预防(常见后续错误) 即使找到设备,仍可能遇到权限问题: ```bash # 永久解决方案 sudo usermod -aG dialout $USER sudo cp /etc/group /etc/group.bak # 备份 echo 'KERNEL=="ttyACM*|ttyUSB*", MODE="0666"' | sudo tee /etc/udev/rules.d/99-serial.rules sudo udevadm control --reload-rules sudo udevadm trigger ``` **重启电脑**使权限永久生效[^1]。 --- #### 疑难解答流程图 ```mermaid graph TD A[报错 Errno 2] --> B{执行 ls /dev/tty*} B -->|有 ttyUSB*| C[修改代码为 /dev/ttyUSB0] B -->|无串口设备| D[检查硬件连接] D -->|设备未识别| E[查看 dmesg | grep tty] E -->|驱动问题| F[安装对应驱动] E -->|无输出| G[更换设备/数据线] C --> H[测试连接] H -->|成功| I[添加动态检测代码] H -->|失败| J[检查权限] ``` > **提示**:Arduino 开发板在 Linux 下常识别为 `ttyACM0`,STM32 开发板常识别为 `ttyUSB0`。实际名称需以 `ls /dev/tty*` 输出为准[^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值