Создание двунаправленной трубы в C для чтения и записи с использованием одной трубы (Linux) - PullRequest
1 голос
/ 19 апреля 2020

Можно ли использовать один канал для записи и чтения между процессами? Мой псевдокод в значительной степени похож на ниже. Я пытался, но он выдал ошибку "плохой дескриптор файла".

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 ]

1 голос
/ 19 апреля 2020

Можно ли использовать один канал для записи и чтения между процессами?

Технически, да, два процесса могут использовать один канал для двунаправленной связи. Для этого нет особых требований к самому каналу, но каждый процесс должен оставлять каждый конец канала открытым, если он хочет использовать этот конец (в отличие от вашего псевдокода). Для ясности: каналы имеют конец записи и конец чтения. Все операции записи в канал должны go до конца записи, и все операции чтения должны выполняться на стороне чтения, но каждый конец может использовать несколько процессов.

Но установить фактическую двунаправленную связь крайне сложно работать правильно таким образом, потому что любые данные, записанные в канал, могут быть прочитаны любым процессом, у которого открыт конец чтения, включая тот, который его записал (хотя фактически каждый байт будет читать каждый байт), и потому что ни один процесс не будет наблюдать конец -файл файла на конце чтения канала, если любой процесс имеет открытый конец записи. Таким образом, чтобы использовать один канал в двух направлениях, вам необходим какой-то дополнительный механизм IP C для посредничества между процессами связи, чтобы гарантировать, что каждый из них получает полные сообщения, что сообщения не становятся заколоченными, и, если это применимо, каждый процесс получает только сообщения, направленные на него.

Гораздо проще установить два канала для каждой пары взаимодействующих процессов, по одному для каждого направления.

1 голос
/ 19 апреля 2020

Когда вы закрываете дескриптор файла, вы больше не можете его использовать.
Канал однонаправленный ; во многих приложениях вы просто выбираете между двумя вашими процессами, какой из них будет читателем, а какой - писателем.
Но с определенной синхронизацией c вы можете поменять местами эти две роли, как предложено в вашем примере (см. редактирование ниже).

Если вам нужен двунаправленный поток, вы можете использовать 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()
...