If the yes
command echos "y" continuously until killed, then it will never get done right?
If it will never get done then how does it pipe it's output to the next command??

- 111
-
1You're probably assuming that the commands in a pipeline are executed sequentially. That's not the case. They're run in parallel, at the same time. Just like my dog is not waiting me to do die before eating the food I had put for him in the bowl, the pipe consumer is not waiting for the pipe producer to die before consuming a line the producer has put into the pipe. – Mar 30 '20 at 02:00
-
@muru find something better. – Mar 30 '20 at 02:03
1 Answers
The yes
program will write to the pipe, concurrently with the reader. If the pipe is empty, the reader will block in the kernel in a call to read()
waiting for more input. If the pipe is full, the write will block in the kernel in a call to write()
waiting for the reader to free up some space in the pipe.
The kernel delivers a SIGPIPE
signal to a process if it ties to write to a pipe that has no reader. When the reading process closes the read-end of the pipe (either explicilty or as a result of its termination), the next time the writing process tries to write to the pipe, it will receive the SIGPIPE
signal.
To illustrate this point, consider this simplified version of the yes
program that prints a continuous stream of y
. This program differs from yes
in that it generates a message when it receives the SIGPIPE
signal:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
static void handler(int sig) {
#define msg "received SIGPIPE signal, terminating\n"
write(2, msg, sizeof msg);
exit(1);
#undef msg
}
int main(void) {
// Instruct the kernel to call the handler() function when
// this process receives the SIGPIPE signal. The default behavior
// when this signal is received is for the process to terminate.
signal(SIGPIPE, handler);
for (;;) {
if (write(1, "y\n", 2) < 0) {
fprintf(stderr, "%s\n", strerror(errno));
return 2;
}
}
return 0;
}
I can compile and run the program and see that it behaves like yes
:
$ gcc ex.c -o myes
$ ./myes
y
y
y
...
If I pipe the output to another process, when that process terminates (and the read-end of the pipe is closed), the myes
program receives the SIGPIPE
signal (as indicated by the associated message).
$ ./myes | head -n5
y
y
y
y
y
received SIGPIPE signal, terminating

- 13,993
-
Thanks for the example code! Does it mean the yes command generates tons of of "y" while the next command is executing but not generating on demand?(even if the next command only required one ‘y’ the yes command could output tons of unneeded “y” ??) – yaquawa Mar 31 '20 at 03:14
-
1That's correct. The pipe is a bounded memory buffer within the kernel. The writer (here the
yes
command) writes to that buffer. The reader reads from the buffer. They run concurrently without any explicit knowledge of one another. If the reader wants/needs/uses only oney
,yes
will write as many as it can to the buffer until either (1) the buffer is full or (2) it receives theSIGPIPE
signal on one of thewrite()
operations after the reader closes the pipe. – Andy Dalton Mar 31 '20 at 13:22