Data written on the write end may be read from the read end. Once all references to the write end are closed, and all remaining data is read, further reads return EOF. If all references to the read end are closed before the write end is closed, further writes generate errors. The pipe object itself is destroyed when all references to both ends are closed.
fds is a pointer to two integers. A file handle for the read end of the pipe is stored in fds[0], and a file handle for the write end is stored in fds[1].
pipe is most often used in conjunction with dup2 and fork to send the standard output of one process to the standard input of another.
In POSIX, pipe I/O of data blocks smaller than a standard constant PIPE_BUF is guaranteed to be atomic. If you implement pipes, you need not necessarily implement POSIX semantics, but you should decide what sort of atomicity guarantees you wish to make and specify them carefully.
EMFILE The process's file table was full, or a process-specific limit on open files was reached. ENFILE The system file table is full, if such a thing exists, or a system-wide limit on open files was reached. EFAULT fds was an invalid pointer.