Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C Unix创建双向管道或类似的任何东西的方法?_C_Sockets_Unix_Serial Port_Named Pipes - Fatal编程技术网

C Unix创建双向管道或类似的任何东西的方法?

C Unix创建双向管道或类似的任何东西的方法?,c,sockets,unix,serial-port,named-pipes,C,Sockets,Unix,Serial Port,Named Pipes,我需要一个基于双向文件系统(如设备节点、命名套接字、命名管道等)的Linux(也可能是其他UNIX系统)下进程间通信的可能性,比方说类似于串行端口,即您可以打开/dev/ttyS0进行读/写,并且可以使用任何工具进行读/写(包括一个普通的cat命令)基本上,在我的例子中,另一部分不是硬件(串行端口),而是另一个完全不相关的过程。是的,我已经读过类似的问题,但是我仍然不确定是否有其他类似的解决方案,如果命名管道不适合我的需要 我能看到: 命名管道/FIFO不是一个解决方案,因为它是单向的(至少在

我需要一个基于双向文件系统(如设备节点、命名套接字、命名管道等)的Linux(也可能是其他UNIX系统)下进程间通信的可能性,比方说类似于串行端口,即您可以打开
/dev/ttyS0
进行读/写,并且可以使用任何工具进行读/写(包括一个普通的
cat
命令)基本上,在我的例子中,另一部分不是硬件(串行端口),而是另一个完全不相关的过程。是的,我已经读过类似的问题,但是我仍然不确定是否有其他类似的解决方案,如果命名管道不适合我的需要

我能看到:

  • 命名管道/FIFO不是一个解决方案,因为它是单向的(至少在一些类似UNIX的系统上,包括Linux),两个命名管道(一个用于RX,一个用于TX)不是一个解决方案

  • (已命名)套接字不是解决方案,因为它们需要特别小心,例如,我不能只是将其“回显”到它中,但我需要connect()等,因此我需要一个自定义客户端来与之交互(见下文)

  • 我对socketpair()有点不确定,因为它会创建两个连接的套接字,但即使如此,另一个进程仍然需要特别准备(我列表中的前一个问题)

  • openpty()
    类似的技巧可能是解决方案(然后由客户端使用
    /dev/pts/…
    ,但我不确定是否在OSX上),不过它很难看,不太便于移植

  • 像内核模块这样的解决方案不是解决方案,因为它根本不可移植,而且无论如何都需要根访问

  • 不基于文件系统的IPC的可能性对我来说也不是解决方案,因为问题的本质

最好的方法是一个双向命名管道(一个进程写入,另一个进程读取,反之亦然,如果它是半双工的,这并不是什么问题),它可以在所有类UNIX系统上工作,至少包括Linux和OSX,但我找不到任何这样的工作方式


我想要的是有一种方法来模拟(仅从用户空间)串行端口之类的东西,这样我甚至可以将其用于一个简单的终端客户端(当然,设置串行参数的ioctl不会起作用,这不是问题!),或者我可以用
echo mmmmmmm>或
cat…
简单地写/读它。我需要它,因为(计算机的)仿真器提供了类似于真实机器串行端口的东西,所以我可以通过它与模拟机器交互。我不能使用其他工具(如
socat
和使用命名套接字,甚至TCP/IP,或其他)由于我也有一个封闭源代码的客户端软件,我无法更改,它期望一个文件名作为“串行端口设备”,但幸运的是,我已经测试过它在各种与串行端口相关的ioctl()调用中不会失败(它可以在命名管道上工作,只是单向性是我的问题),所以我需要解决“仅”这个问题,它可以工作。

唯一允许您读取(2)
和写入(2)的系统对象每个描述符上分别有套接字和pty。只有这些对象有两个用于发送和接收数据的队列。所有其他管道对象只有一个,当您收到一对描述符(例如,对于未命名管道)时,如果您下一步读到它,就会立即收到您所写的内容

在这种情况下,我不建议使用pty接口,因为正如您所说,在能够传输之前,您必须进行一些内务处理,并且必须处理设备参数(如
termios
config、波特率和设备级别的字符解释)

getsocketpair(3)
是一个库函数,它已经为您提供了一对已连接的套接字,并允许您在调用中指定所需的套接字类型(网络套接字、unix套接字等)

int res, sfds[2];
res = getsocketpair(PF_LOCAL, SOCK_STREAM, 0, sfds);
如果成功,将返回
0
,并在
sfds
数组中返回两个已连接的套接字。在BSD系统中(OS/X是从中派生的),
getsocketpair(2)
是一个系统调用,它允许内核选择一个有效的版本(如示例所示),该版本没有网络协议强加的开销

注 正如您在评论中所说,您的程序可能不仅执行
read(2)
write(2)
调用,而且也是一个从用户处获取原始输入的程序(如切换无回声模式以获取密码或作为交互式程序获取raw输入,如
vi(1)
emacs(1)
do)


在这种情况下,我建议你下载我的程序,研究并修改它,以便为你工作。它完全符合你的要求。它分配一对
pty
s,并进行输入/输出。它还要求你使用tty行,但这仅仅是因为它将终端设置从你的stdin复制到pty行。这是一个简单的程序,专门设计的只是教人们如何使用
pty(7)
接口,在FreeBSD、Mac/OS X和linux中运行良好。因此,该程序将tty输入/输出速度减慢到从pty中调整的波特率,这样您就可以像使用旧的串行tty线路一样查看输出。这种减慢是在一个单独的例程中进行的,因此可以很容易地从源代码中消除。

我想不出来除了使用伪终端之外,任何其他解决方案都是如此。但如果我正确理解了这个问题,我认为这对您来说确实是一个解决方案。OSX的可移植性应该是可能的,因为有BSD伪终端。我不相信您想要的东西可以做到——这可能就是您无法找到任何可以做到的东西的原因第二个过程是如何知道连接事物的方式的?它应该响应第一个过程,还是重新开始?第三个过程是如何连接的