The linked question image says (material added to question while answer being written — leaving it here too because I can leave some [sic] comments):
This project simulates Unix pipe command. …
The parent process takes in two command-line arguments, which are two independent executable programs: p1 and p2. The parent open [sic] a kernel pipe and forks child process. The child inherits the open pipe from parent.
The parent process links its standard output to the input end of the pipe and closes the output end, then it replaces itself with p1. The child process links is [sic] standard input to the output end of the pipe and closes the input end, then the child replaces itself with p2.
… Each pipe is coded as an integer array of two file descriptors (int fd[2]). fd[0] is the input end of the pipe, and fd[1] is the output end of the pipe. …
The terminology 'input end' and 'output end' is defined.
You're left with connecting a read descriptor (fd[0]
) to a write channel (FILENO_STDOUT
), which "can be done" but is normally meaningless. The directions of the channels are conventional and ensure interworking between programs. But you could subvert the convention for one set of programs — which makes the code useless in other contexts. Unless the progams p1
and p2
are specially created to read from file descriptor 1 (FILENO_STDOUT
) and to write to file descriptor 0 (FILENO_STDIN
), the information generated by p1
will not be relayed to p2
.
- The exercise has bugs in it.
You can do exactly as told and demonstrate that it does not work. You can create a working solution which does things in the orthodox way and demonstrate that it does work.
I'd also quibble with the terminology 'pipe command'. On macOS, there is an actual command called pipe(8)
:
NAME
pipe - Postfix delivery to external command
SYNOPSIS
pipe [generic Postfix daemon options] command_attributes...
DESCRIPTION
The pipe(8) daemon processes requests from the Postfix queue manager to deliver messages to external commands. This program
expects to be run from the master(8) process manager.
The |
notation is not a command; it is a method of inter-process communication, IPC.
A better description would be:
This project simulates the Unix shell pipe notation p1 | p2.
The question title is 'Can pipe be used to connect 2 file descriptors of the same process?' The question in the title is not actually asked in the body of the question. The answer to the question in the title is "Yes". Indeed, the pipe()
system call creates two file descriptors in the same process which are connect such that data written on one of the file descriptors can be read from the other file descriptor. That's the point of the pipe()
system call.
If you need to set up the link between a specific pair of file descriptors, you have to call pipe()
, then dup2()
twice, then close()
twice. The pipe()
call returns 2 arbitrary file descriptor numbers. The dup2()
calls connect the desired numbers to the numbers provided by pipe()
; the close()
calls disconnect the numbers returned by pipe()
. The only gotcha to watch for is if the numbers returned by pipe()
collide with the desired numbers. Then you have to be more fiddly — probably two calls to dup()
with the descriptors returned by pipe()
, two calls to close()
on the descriptors returned by pipe()
, then two calls to dup2()
to map the descriptors from dup()
to the desired numbers, and two more calls to close()
to close the descriptors from dup()
. (Note that dup()
chooses the file descriptors for you; dup2()
allows you to dictate the file descriptor returned.)
There is still the sick possibility that pipe()
returns one of the two descriptors desired; then one of the dup()
calls returns the other of the two descriptors. Just add another dup()
into the sequence. Don't call close()
until you've called dup2()
.
unix self-pipe
– wildplasser