title: Which type of buffering is used by the two file descriptors returned by `pipe`?
body: <p>As per the manual of <code>man 2 pipe</code>, which says that[emphasis mine]:</p>
  <blockquote>
  <p>pipe()  creates  a pipe, a unidirectional data channel that can be used for interprocess communication.  The array pipefd is used to return <em><strong>two file descriptors</strong></em> referring to the ends of the pipe.  pipefd[0] refers to the read end of the pipe.  pipefd[1] refers to the write end of the pipe.  Data written  to  the write end of the pipe is buffered by the kernel until it is read from the read end of the pipe. For further details, see pipe(7)</p>
  </blockquote>
  <p>But the quotation above and <code>man 7 pipe</code> do not mention which type of buffering is used by the two file descriptors returned by <code>pipe</code>?</p>
  <p>And as per the <a href="https://www.oreilly.com/library/view/unix-filesystems-evolution/9780471456759/chap04-sec004.html" rel="nofollow noreferrer">document</a>, which says there are three types of buffering[emphasis mine]:</p>
  <blockquote>
  <p>Standard I/O Library Buffering
  The stdio library buffers data with the goal of minimizing the number of calls to the read() and write() system calls. There are three different types of buffering used:</p>
  </blockquote>
  <blockquote>
  <p><strong>Fully (block) buffered</strong>. As characters are written to the stream, they are buffered up to the point where the buffer is full. At this stage, the data is written to the file referenced by the stream. Similarly, reads will result in a whole buffer of data being read if possible.</p>
  </blockquote>
  <blockquote>
  <p><strong>Line buffered</strong>. As characters are written to a stream, they are buffered up until the point where a newline character is written. At this point the line of data including the newline character is written to the file referenced by the stream. Similarly for reading, characters are read up to the point where a newline character is found.</p>
  </blockquote>
  <blockquote>
  <p><strong>Unbuffered</strong>. When an output stream is unbuffered, any data that is written to the stream is immediately written to the file to which the stream is associated.</p>
  </blockquote>
  <blockquote>
  <p>The ANSI C standard dictates that standard input and output should be fully buffered while standard error should be unbuffered. Typically, standard input and output are set so that they are line buffered for terminal devices and fully buffered otherwise.</p>
  </blockquote>
  <p>And I did a simple test on <code>Ubuntu16.04</code>, here is the <a href="https://godbolt.org/z/E7Wz873dq" rel="nofollow noreferrer">code snippet</a>:</p>
  <pre><code>#include &lt;sys/wait.h&gt;
  #include &lt;stdio.h&gt;
  #include &lt;stdlib.h&gt;
  #include &lt;unistd.h&gt;
  #include &lt;string.h&gt;
  #include &lt;string&gt;
  #include &lt;thread&gt;
  #include &lt;array&gt;
  #include &lt;iostream&gt;
  
  int
  main(int argc, char *argv[])
  {
      int pipefd[2];
      pid_t cpid;
      std::array&lt;char, 1024&gt; buf;
      
      if (pipe(pipefd) == -1) {
          perror(&quot;pipe&quot;);
          exit(EXIT_FAILURE);
      }
      cpid = fork();
      if (cpid == -1) {
          perror(&quot;fork&quot;);
          exit(EXIT_FAILURE);
      }
      if (cpid == 0) {    /* Child reads from pipe */
          close(pipefd[1]);          /* Close unused write end */
          int size;
          while ((size = read(pipefd[0], buf.data(), buf.size())) &gt; 0)
               std::cout &lt;&lt; size &lt;&lt; std::endl;
          write(STDOUT_FILENO, &quot;\n&quot;, 1);
          close(pipefd[0]);
          _exit(EXIT_SUCCESS);
      } else {            /* Parent writes argv[1] to pipe */
          close(pipefd[0]);          /* Close unused read end */
          std::string str{&quot;hello world&quot;};
          for(int i=0; i&lt;3; i++)
          {
              write(pipefd[1], str.c_str(), str.size());
              std::this_thread::sleep_for(std::chrono::seconds(3));
          }
          close(pipefd[1]);          /* Reader will see EOF */
          wait(NULL);                /* Wait for child */
          exit(EXIT_SUCCESS);
      }
  }
  </code></pre>
  <p>Here is the output of the aforementioned code snippet:</p>
  <pre><code>11
  //about three seconds later
  11
  //about three seconds later
  </code></pre>
  <p>You see that what the write end writes to the pipe does not contain a <code>\n</code>, whereas the read end could read out a full string every three seconds. So I think that the two file descriptors returned by <code>pipe</code> are neither <code>block buffered</code> nor <code>line buffered</code>. Two choices are stripped out, then there is only <code>unbuffered buffering</code>.</p>
  <p>But the manual of <code>man 7 pipe</code> also says that:</p>
  <blockquote>
  <p>PIPE_BUF
  POSIX.1-2001 says that write(2)s of less than PIPE_BUF bytes must be atomic: the output data is written to the pipe as a contiguous sequence.  Writes of more
  than PIPE_BUF bytes may be nonatomic: the kernel may interleave the data with data written by other processes.  POSIX.1-2001 requires PIPE_BUF to be at least
  512 bytes.  (On Linux, PIPE_BUF is 4096 bytes.)</p>
  </blockquote>
  <p>As per the quotation above, there are buffers for the two file descriptors indeed.</p>
  <p>So I am really confused which type of buffering is used by the two file descriptors returned by <code>pipe</code>. And since there is buffer provided to each of the file descriptor, how could I receive the  string on time(i.e. one string every three seconds other than three strings together)?</p>
  <p>Could anybody shed some light on this matter?</p>