在C中创建双向管道以使用一个管道进行读取和写入(Linux)

时间:2020-04-19 11:41:30

标签: c process pipe fork ipc

是否可以使用一个管道在进程之间进行写入和读取?我的伪代码很像下面。我试过了,但是给了我一个错误,提示“错误的文件描述符”。

create fd[2]
create pipe(fd)

parent:
     close fd[0]
     write something to fd[1]
     close fd[1]
     // wait for child's signal
     close fd[1]
     read the response fd[0]
     close fd[0]

child:
     close fd[1]
     read the pipe fd[0]
     close fd[0]

    // write an answer to the parent via the existing pipe
    // no need to close fd[0], since it's already closed
     write the answer fd[1]
     close fd[1]
     signal to the parent

非常感谢。

2 个答案:

答案 0 :(得分:1)

关闭文件描述符后,将无法再使用它。
管道是单向;在许多应用中,您只需决定 在您的两个过程之间,哪个将成为读者,哪个 一个会是作家。
但是通过特定的同步,您可以交换这两个角色 按照示例中的建议进行操作(请参见下面的修改)。

如果您需要双向流,可以使用socketpair(PF_LOCAL, SOCK_STREAM, 0, fd)


修改,关于立即关闭

当您确定要关闭管道的一端时, 您的流程将不再需要它。

别指望在文件结束之前检测到文件结尾 同步信号,因为管道的另一端不在 已关闭。

此示例可能会有所帮助。

#!/usr/bin/env python

import sys
import os
import signal

fd=os.pipe()
p=os.fork()
if p==0:
  signal.signal(signal.SIGUSR1, lambda signum, frame: 0)
  os.write(fd[1], b'A')
  os.close(fd[1]) # I will never write again to this pipe
  signal.pause() # wait for the signal before trying to read
  b=os.read(fd[0], 1)
  os.close(fd[0]) # I will never read again from this pipe
  sys.stdout.write('child got <%s>\n'%b)
else:
  a=os.read(fd[0], 1)
  os.close(fd[0]) # I will never read again from this pipe
  sys.stdout.write('parent got <%s>\n'%a)
  os.kill(p, signal.SIGUSR1) # now the child is allowed to read
  os.write(fd[1], b'B')
  os.close(fd[1]) # I will never write again to this pipe
  os.wait()

答案 1 :(得分:1)

是否可以使用一个管道在进程之间进行读写?

从技术上讲,是的,两个进程可以使用单个管道进行双向通信。启用此功能的管道本身并没有特殊要求,但是每个进程都必须使每个管道端都保持打开状态,只要他们想使用该端即可(与您的伪代码相反)。不过要清楚一点:管道具有写端和读端。对管道的所有写操作都必须到达写端,并且所有读操作都必须在读端执行,但是每个端都可以使用多个进程。

但是以这种方式正确地进行实际的双向通信是非常棘手的,因为写入到管道的任何数据都可以被任何具有读取端打开状态的进程读取,包括写入该数据的进程(尽管只有一个可以读取)实际上会读取每个字节),因为只要 any 进程打开了写入端,就没有进程会在管道的读取端观察到文件结束信号。因此,要双向使用单个管道,您需要一些其他IPC机制来在通信进程之间进行调解,以确保每个进程都接收完整的消息,消息不会混合在一起,并且,如果适用,每个进程仅接收定向的消息。

为每对通信过程分别设置两个管道要容易得多,每个方向都需要一个管道。