从串行设备(/ 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()等需要正常,以便现有的二进制文件工作
我试图找到struct fdtable或struct file将让我确定打开的文件是套接字还是管道的成员.
我能找到的唯一途径是:
struct file f ....;
f.path->mnt->mnt_devname
Run Code Online (Sandbox Code Playgroud)
这将返回挂载点处的设备名称,所有套接字/管道分别显然属于sockfs或pipefs.
是否有更快的方法来检查打开的文件是使用struct file或fdtable的不同成员的套接字还是管道?
注意:我使用的是2.6.24中的内核定义
我正在尝试使用bash打开一个新的描述符来编写额外的诊断消息.我不想使用stderr,因为stderr应该只包含bash调用的程序的输出.我还希望我的自定义描述符可由用户重定向.
我试过这个:
exec 3>/dev/tty
echo foo1
echo foo2 >&2
echo foo3 >&3
Run Code Online (Sandbox Code Playgroud)
但是当我尝试重定向fd 3时,输出仍然写入终端.
$ ./test.sh >/dev/null 2>/dev/null 3>/dev/null
foo3
Run Code Online (Sandbox Code Playgroud) 在BASH脚本中,我们可以在后台运行多个进程,这些进程使用命名管道进行互通,在文件系统上注册FIFO.这方面的一个例子可能是:
#!/bin/bash
mkfifo FIFO
# BG process 1
while :; do echo x; done & >FIFO
# BG process 2
while :; do read; done & <FIFO
exit
Run Code Online (Sandbox Code Playgroud)
我想知道是否可以在不使用文件系统上的FIFO的情况下在脚本的后台进程之间进行相同的相互通信,也许可以使用某种文件描述符重定向.
我在Linux上的C程序中遇到了问题.
我知道当一个进程被分叉时,子进程从父进程继承了一些东西,包括打开文件描述符.
问题是我正在编写一个多进程服务器应用程序,其主进程接受新连接并将描述符放入共享内存.
当子进程尝试从共享内存中读取其中一个描述符时,select()我收到EBADF错误!
子进程如何读取并使用父进程分叉后创建的套接字(或一般的任何文件描述符)?
在C伪代码中:
while (1) {
fifo = open("fifo", O_RDONLY | O_NONBLOCK);
fd_set read;
FD_SET(fifo, &read);
select(nfds, &read, NULL, NULL, NULL);
}
Run Code Online (Sandbox Code Playgroud)
进程在触发时休眠,select()直到另一个进程写入fifo.之后它总是会找到fifo一个可读的文件描述符.
如何避免这种行为(也就是说,在fifo读过一次之后,如何让它在被另一次写入之前被发现是不可读的?)
我有一个我正在做的套接字select(),等待其他进程写入.一旦写入,我读取数据,并将其写入另一个文件描述符.我的问题是,如果有一种方法可以将套接字桥接到文件描述符,那么当数据就绪时,它会自动写入另一个文件描述符?
这样,我可以抛出我正在使用的缓冲区,并省略系统中的一个线程.
我有兴趣知道我可以期待的文件描述符的有效值.
请让我解释一下.我知道,例如,当我#include <unistd.h>在我的linux系统上使用然后调用打开文件进行阅读时:
int fileDescriptor;
fileDescriptor = open("/some/filename",O_RDONLY);
Run Code Online (Sandbox Code Playgroud)
可能会发生错误,因此我收到-1.
毫无疑问,( - 1)否定的必须具有某种特殊含义.是否所有其他值都是有效的文件描述符?即也是-2和-1023等负面的?
假设int是4个字节(sizeof(int)==4),那么就是
(-1) = 10000000 0000000 00000000 00000001
Run Code Online (Sandbox Code Playgroud)
将是唯一可检测的无效文件描述符?其他人会喜欢:
(0) = 00000000 0000000 00000000 00000000 (-2) = 10000000 0000000 00000000 00000010(2) = 00000000 0000000 00000000 00000010 好吗?由于文件描述符可以存储4个字节,因此我可以拥有最多(2 ^(8*4)-1)个有效文件描述符,因此这将是我可以打开的最大文件数,对吗?
再说一遍:
我应该期望(有效)文件描述符是什么?
任何值,但-1?
我将一些代码移植到Darwin OS X,作为更改的一部分,我们从gcc转到clang编译器.
在代码中,有一个功能可追溯到2005年,并在互联网上发布了几个地方.它为几个不同的旧版GCC提供了功能,我已经删除了它提供的最后一个版本,v3.4.0或更高版本.代码取决于两个GCC特定类:__gnu_cxx::stdio_filebuf和__gnu_cxx::stdio_sync_filebuf.
//! Similar to fileno(3), but taking a C++ stream as argument instead of a
//! FILE*. Note that there is no way for the library to track what you do with
//! the descriptor, so be careful.
//! \return The integer file descriptor associated with the stream, or -1 if
//! that stream is invalid. In the latter case, for the sake of keeping the
//! code as similar to fileno(3), errno …Run Code Online (Sandbox Code Playgroud)