从串行设备(/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(伪终端)的从属端?
- 我希望阅读器打开 pty 的从端以在阅读器打开 pty 后严格接收写入的数据(如果我的多写过程只是在阅读器打开从端之前写入数据一段时间,数据将缓冲起来并最终写入器将阻塞,从属读取器在打开时将立即获取所有缓冲数据——这是不可取的,因为我希望它只获取在紧邻时间附近生成的数据)
——它必须是一个 pty,而不是命名管道、套接字等,因为 isatty() 和 tcsetattr() 等需要正常,以便现有的二进制文件工作