Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to wait for the other end of a named pipe to be open?

I would like to exchange data between 2 processes (A and B) using 2 named pipes (a2b and b2a) as follows:

  1. Process A creates the a2b and b2a pipes using mkfifo(3).
  2. Process A starts process B (either using fork(), exec*() or even system())
  3. A waits until B open()s a2b and b2a
  4. A write()s data to a2b
  5. B read()s data from a2b
  6. B write()s data to b2a
  7. A read()s data from b2a

How can I make process A wait until process B open()s the other ends of the named pipes? -- i.e. How do I implement step 3?

EDIT 1: As mentioned by @EJP, it is possible to implement step 3 using read/write/select. However, I would like to know if there are other approaches.

like image 306
maddouri Avatar asked Feb 09 '18 00:02

maddouri


People also ask

How do you open a named pipe?

Processes can use the open() function to access named pipes and then use the regular I/O functions for files, such as read() , write() , and close() , when manipulating named pipes. Buffered I/O functions can also be used to access and manipulate named pipes.

What is the difference between a named pipe and an unnamed pipe?

An unnamed pipe is a direct connection between two commands running in the same terminal. If we want to send output from a command in one terminal to another command in a different terminal, we can use a named pipe, or FIFO. FIFO stands for first in, first out. This is a pipe that exists in the file system.

Are unnamed pipes bidirectional?

Unnamed pipes They can be used even among unrelated processes. They can be used only between related processes. They are bidirectional, which means the same FIFO can be read from as well as written into.

Are named pipes permanent?

Also unlike their Unix counterparts, named pipes are volatile (removed after the last reference to them is closed).


1 Answers

The behavior of POSIX open is specified for FIFOs. If you're using Linux, man 7 fifo has some nice discussion:

The kernel maintains exactly one pipe object for each FIFO special file that is opened by at least one process. The FIFO must be opened on both ends (reading and writing) before data can be passed. Normally, opening the FIFO blocks until the other end is opened also.

A process can open a FIFO in nonblocking mode. In this case, opening for read-only succeeds even if no one has opened on the write side yet and opening for write-only fails with ENXIO (no such device or address) unless the other end has already been opened.

So you have two options:

  1. use blocking mode and the open call will block till the other end is open, or
  2. use non-blocking mode and spin on the open call until it succeeds.

If your requirements permit, you can skip a named pipe (FIFO) altogether and just use a pipe. The child process inherits open file descriptors to each end of the pipe and can use either one as needed (don't forget to close the unneeded descriptor).


However, considering your end goal is bi-directional communication, might I suggest a (unix domain) socket and some IO multiplexing strategy (select, poll, epoll, kqueue, etc.)?

like image 54
dcow Avatar answered Sep 19 '22 05:09

dcow