Unix 方法来创建双向管道或任何类似的行为?
Unix way to create bi-directional pipes or anything which acts like that?
我需要一个基于双向文件系统(例如设备节点、命名套接字、命名管道等)的进程间通信可能性 Linux(可能还有其他 UNIX 系统) ), 假设类似于串行端口,即您可以为 read/write 打开 /dev/ttyS0
并且您可以使用 any 工具(包括普通 cat
命令)基本上,就我而言,另一部分不是硬件(串行端口),而是另一个但完全不相关的过程。是的,我已经阅读过关于 SO 的类似问题,但是我仍然不确定是否有 other 类似的解决方案,如果命名管道不适合我的需求。
我能看到的:
named pipe/FIFO 不是一个解决方案,因为它是单向的(至少在一些类 UNIX 系统上,包括 Linux),两个命名管道(一个用于 RX和一个用于 TX)不是解决方案
(named) 套接字不是解决方案,因为它们需要特别小心,例如,我不能只回显 "into" 它,但我需要 connect() 等,所以我会需要自定义客户端与之交互(见下文)
我对 socketpair() 有点不确定,因为它创建了两个连接的套接字,但即便如此,另一个进程仍然需要特殊准备(我列表中的前一个问题)
openpty()
之类的技巧可以解决(然后由客户使用 /dev/pts/...
,不过我不确定 OSX),但是它很难看,不太便携...
内核模块之类的解决方案不是解决方案,因为它根本不可移植,而且无论如何都需要 root 访问权限
不是基于文件系统的 IPC 可能性对我来说也不是解决方案,因为问题的本质
最好的方法是双向命名管道(一个进程写入它,另一个进程可以读取,反之亦然,如果它是半双工的,虽然问题不大),它适用于所有类 UNIX 系统,至少包括 Linux 和 OSX,但是我找不到任何像这样工作的东西。
我想要的是有一种方法来模拟(仅来自用户 space)类似串行端口的东西,这样我什至可以将它与一个简单的终端客户端一起使用(当然,ioctl 的设置up 串行参数不起作用,这不是问题!),或者我可以用 echo mmmmm > ...
或 cat ...
简单地 write/read 它。我需要它,因为(计算机的)仿真器提供了类似于真机串行端口的东西,所以我可以通过它与仿真机进行交互。我不能使用其他工具(比如 socat
和使用命名套接字,甚至 TCP/IP 或其他工具)因为我还有一个我无法更改的封闭源客户端软件,它需要一个文件名作为"serial port device",但是我已经测试过它不会在各种串行端口相关的 ioctl() 调用上失败,幸运的是(它可以在命名管道上工作,只是单向性是我的问题),所以我需要解决"only"这个问题,它会解决的。
允许您在每个描述符上单独 read(2)
和 write(2)
的唯一系统对象是套接字和 pty。这些是仅有的具有用于发送和接收数据的两个队列的对象。所有其他 pipe 东西只有一个,当你收到一对描述符(例如对于未命名的管道)时,如果你接下来阅读它,你写的内容将立即收到。
我不建议在这种情况下使用 pty 接口,因为正如你所说,在能够传输之前你必须做一些内务处理并且你必须处理设备参数(比如 termios
设备级别的配置、波特率和字符解释)
getsocketpair(3)
是一个库函数,它已经为您提供了一对 已连接的套接字 ,并允许您指定套接字的类型(网络套接字、unix 套接字等)你喜欢的来电。
int res, sfds[2];
res = getsocketpair(PF_LOCAL, SOCK_STREAM, 0, sfds);
将 return 0
如果成功并且 sfds
数组中有两个已连接的套接字。在 BSD 系统中(如 OS/X 派生自),getsocketpair(2)
是一个系统调用,它允许内核 select 一个没有开销的高效版本(如示例所示)由网络协议强加。
注意
正如您在评论中所说,您的程序很可能不仅执行 read(2)
和 write(2)
调用,而且还是一个从用户那里获取原始输入的程序(比如切换无回声获取密码或获取 raw 输入作为交互式程序的模式,例如 vi(1)
或 emacs(1)
do)
在那种情况下,我建议您下载我的程序 slowtty
并研究和修改它以适合您。它正是你想要的。它分配一对 pty
并执行 input/output。它还要求您使用 tty 线路,但这只是因为它将终端设置从您的 stdin 复制到 pty 线路。这是一个简单的程序,旨在教人们如何使用 pty(7)
界面,它在 FreeBSD、Mac/OS X 和 linux 中运行良好。因此,程序将 tty input/output 减慢到从属 pty 中调整的波特率,因此它允许您查看输出,就好像您在使用旧的串行 tty 线路一样。减速是在一个单独的例程中进行的,因此可以很容易地从源代码中删除。
我需要一个基于双向文件系统(例如设备节点、命名套接字、命名管道等)的进程间通信可能性 Linux(可能还有其他 UNIX 系统) ), 假设类似于串行端口,即您可以为 read/write 打开 /dev/ttyS0
并且您可以使用 any 工具(包括普通 cat
命令)基本上,就我而言,另一部分不是硬件(串行端口),而是另一个但完全不相关的过程。是的,我已经阅读过关于 SO 的类似问题,但是我仍然不确定是否有 other 类似的解决方案,如果命名管道不适合我的需求。
我能看到的:
named pipe/FIFO 不是一个解决方案,因为它是单向的(至少在一些类 UNIX 系统上,包括 Linux),两个命名管道(一个用于 RX和一个用于 TX)不是解决方案
(named) 套接字不是解决方案,因为它们需要特别小心,例如,我不能只回显 "into" 它,但我需要 connect() 等,所以我会需要自定义客户端与之交互(见下文)
我对 socketpair() 有点不确定,因为它创建了两个连接的套接字,但即便如此,另一个进程仍然需要特殊准备(我列表中的前一个问题)
openpty()
之类的技巧可以解决(然后由客户使用/dev/pts/...
,不过我不确定 OSX),但是它很难看,不太便携...内核模块之类的解决方案不是解决方案,因为它根本不可移植,而且无论如何都需要 root 访问权限
不是基于文件系统的 IPC 可能性对我来说也不是解决方案,因为问题的本质
最好的方法是双向命名管道(一个进程写入它,另一个进程可以读取,反之亦然,如果它是半双工的,虽然问题不大),它适用于所有类 UNIX 系统,至少包括 Linux 和 OSX,但是我找不到任何像这样工作的东西。
我想要的是有一种方法来模拟(仅来自用户 space)类似串行端口的东西,这样我什至可以将它与一个简单的终端客户端一起使用(当然,ioctl 的设置up 串行参数不起作用,这不是问题!),或者我可以用 echo mmmmm > ...
或 cat ...
简单地 write/read 它。我需要它,因为(计算机的)仿真器提供了类似于真机串行端口的东西,所以我可以通过它与仿真机进行交互。我不能使用其他工具(比如 socat
和使用命名套接字,甚至 TCP/IP 或其他工具)因为我还有一个我无法更改的封闭源客户端软件,它需要一个文件名作为"serial port device",但是我已经测试过它不会在各种串行端口相关的 ioctl() 调用上失败,幸运的是(它可以在命名管道上工作,只是单向性是我的问题),所以我需要解决"only"这个问题,它会解决的。
允许您在每个描述符上单独 read(2)
和 write(2)
的唯一系统对象是套接字和 pty。这些是仅有的具有用于发送和接收数据的两个队列的对象。所有其他 pipe 东西只有一个,当你收到一对描述符(例如对于未命名的管道)时,如果你接下来阅读它,你写的内容将立即收到。
我不建议在这种情况下使用 pty 接口,因为正如你所说,在能够传输之前你必须做一些内务处理并且你必须处理设备参数(比如 termios
设备级别的配置、波特率和字符解释)
getsocketpair(3)
是一个库函数,它已经为您提供了一对 已连接的套接字 ,并允许您指定套接字的类型(网络套接字、unix 套接字等)你喜欢的来电。
int res, sfds[2];
res = getsocketpair(PF_LOCAL, SOCK_STREAM, 0, sfds);
将 return 0
如果成功并且 sfds
数组中有两个已连接的套接字。在 BSD 系统中(如 OS/X 派生自),getsocketpair(2)
是一个系统调用,它允许内核 select 一个没有开销的高效版本(如示例所示)由网络协议强加。
注意
正如您在评论中所说,您的程序很可能不仅执行 read(2)
和 write(2)
调用,而且还是一个从用户那里获取原始输入的程序(比如切换无回声获取密码或获取 raw 输入作为交互式程序的模式,例如 vi(1)
或 emacs(1)
do)
在那种情况下,我建议您下载我的程序 slowtty
并研究和修改它以适合您。它正是你想要的。它分配一对 pty
并执行 input/output。它还要求您使用 tty 线路,但这只是因为它将终端设置从您的 stdin 复制到 pty 线路。这是一个简单的程序,旨在教人们如何使用 pty(7)
界面,它在 FreeBSD、Mac/OS X 和 linux 中运行良好。因此,程序将 tty input/output 减慢到从属 pty 中调整的波特率,因此它允许您查看输出,就好像您在使用旧的串行 tty 线路一样。减速是在一个单独的例程中进行的,因此可以很容易地从源代码中删除。