从串行设备(/ dev / ttyXX)读取多个进程使得两个进程都无法获取所有数据 - 数据将以某种方式在它们之间进行分割。我想编写一个从串行设备读取的程序,创建几个主/从pty对,然后允许从串行设备读取的程序从ptys读取,以便所有读取进程接收数据从串行设备开始,让ptys就像串行设备一样,当他们从pty开始读取时,他们只得到最新的数据。换句话说,在开始阅读之前你不会得到任何数据(这是我的经验,这就是/ dev / ttyXX设备的工作原理,或者至少是我读的RS-232风速计)。命名管道可以通过捕获SIGPIPE来模仿这些语义,以确定没有读取器,因此我们可以选择不写入该特定命名管道。但是,在与命名管道通信时,写入使用终端的某些二进制文件可能会失败,因为对isatty()的检查和对tcsetattr()等调用的错误条件可能会导致失败的情况。这里的关键是能够使用为终端编写的现有二进制文件。
因此,如果我能够检测到pty的slave端何时被打开以进行读取,那么这应该给出与命名管道情况中没有SIGPIPE大致相同的语义。我注意到HP-UX将TIOCTRAP作为ioctl()命令,它似乎完全符合我的要求,但遗憾的是它在Linux上不可用。
我已经阅读了几天的参考文献,这类事情的选项数量是惊人的。答案可能在于终端设置,阻塞/非阻塞行为,在某处设置缓冲区大小,从poll()/ select()报告的条件,或某些组合。但我似乎找不到任何东西。我想知道是否有可能我需要编写自己的设备驱动程序,但似乎我应该能够做到这一点而不用那么远。
因此,澄清:
- 问题是:如何检测有人在Linux中打开pty(伪终端)的从属端?
- 我希望读者打开pty的slave端接收读取器打开pty后严格写入的数据(如果我的多次写入过程只是在读取器打开从属端之前写入数据一段时间,数据将缓冲并且最终编写器将阻塞,并且从属读取器在打开时将立即获得所有缓冲数据 - 这是不可取的,因为我希望它只获得在紧邻时间附近生成的数据)
- 必须是pty,而不是命名管道,套接字等,因为isatty()和tcsetattr()等需要正常,以便现有的二进制文件工作
答案 0 :(得分:10)
您无法找到这个的原因是因为没有特定的文档接口允许它。但是,有一个技巧可以让你这样做。打开伪终端主机(假设这里是文件描述符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()
所有主ttys,并将数据发送给任何没有设置POLLHUP
的人。
答案 1 :(得分:3)
在slave pty上添加一个inotify监视并对其进行轮询。您可以在打开时获得inotify事件。然后,您可以在inotify文件描述符和主pty文件描述符上进行轮询。您可以获得open(IN_OPEN)的inotify事件。这将在从属方打开时取消阻止轮询。