从串行设备 (/dev/ttyXX) 读取多个进程使得两个进程无法获取所有数据——数据将以某种方式在它们之间拆分。我想编写一个从串行设备读取的程序,创建几个主/从 pty 对,然后允许从串行设备读取的程序改为从 pty 读取,以便所有读取进程接收数据从串行设备开始,并让 pty 像串行设备一样工作,因为当它们开始从 pty 读取时,它们只会获得最新的数据。换句话说,在开始读取之前,您不会获得任何写入的数据(我的经验是/dev/ttyXX 设备是这样工作的,或者至少是我正在读取的 RS-232 风速计)。命名管道可以通过捕获 SIGPIPE 来模拟这些语义,以确定没有读取器,因此我们可以选择不写入该特定命名管道。但是,一些为使用终端而编写的二进制文件在与命名管道通信时可能会失败,因为检查 isatty() 和 tcsetattr() 等调用的 errno 条件可能会导致失败条件。这里的关键是能够使用为终端编写的现有二进制文件。

因此,如果我可以检测到何时打开 pty 的从属端进行读取,这应该给我提供与命名管道案例中没有 SIGPIPE 大致相同的语义。我注意到 HP-UX 将 TIOCTRAP 作为 ioctl() 命令,这似乎完全符合我的要求,但遗憾的是它在 Linux 上不可用。

我几天来一直在阅读引用资料,这种类型的选项数量惊人。答案可能在于终端设置、阻塞/非阻塞行为、在某处设置缓冲区大小、从 poll()/select() 报告的条件或某些组合。不过,我似乎找不到任何东西。我想知道是否有可能我需要编写自己的设备驱动程序,但似乎我应该能够做到这一点而不必走那么远。

所以,为了澄清:
- 问题是:我如何检测何时有人在 Linux 中打开 pty(伪终端)的从属端?
- 我想要一个reader打开pty的slave端来接收reader打开pty后严格写入的数据(如果我的多写过程只是在reader打开slave端之前写了一段时间数据,数据会缓冲起来,最终,写入器将阻塞,而从读取器在打开时将立即获取所有缓冲数据——这是不可取的,因为我希望它只获取在紧邻时间附近生成的数据)

- 它必须是 pty,而不是命名管道、套接字等,因为 isatty() 和 tcsetattr() 等需要确定,以便现有二进制文件工作

最佳答案

您找不到它的原因是因为没有专门允许它的文档化接口(interface)。但是,有一个技巧可以让您做到这一点。打开伪终端主机(这里假设为文件描述符 ptm )后,打开并立即关闭从机端:

close(open(ptsname(ptm), O_RDWR | O_NOCTTY));

这会在 tty 主机上设置 HUP 标志。您现在使用 poll() 定期轮询 HUP 标志(例如,每当数据来自您的数据源时):
struct pollfd pfd = { .fd = ptm, .events = POLLHUP };
poll(&pfd, 1, 10 /* or other small timeout */);

if (!(pfd.revents & POLLHUP))
{
    /* There is now a reader on the slave side */
}

如果读取器离开,将再次设置 POLLHUP

在您的情况下,您可能甚至不需要从一个循环到下一个循环记住给定的 pty 是否有读取器 - 只需阻止数据源上的 read(),然后当数据可用时,同时 poll() 所有主 tty 和将数据发送给没有设置 POLLHUP 的任何一个。

关于linux - 如何检测何时有人在 Linux 中打开 pty(伪终端)的从属端?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/3486491/

10-14 16:03