I have written a demo program for pipes.
A process forks, the parent writes a number to pipe, the child reads it, divides by 2, and sends it back. The parent reads the number and prints it.
#include <stdio.h> #include <unistd.h> #include <fcntl.h> #include <sys/types.h> #include <sys/stat.h> #define COLOR_YELLOW "33[1;33m" #define COLOR_GREEN "33[1;32m" #define COLOR_RED "33[1;31m" #define COLOR_CLEAR "33[0m" int main(int argc, char *argv[]) { printf(COLOR_YELLOW "Let the story begin\n"); printf("I am a parent, my pid = %d\n", getpid()); char c; int pipes[2]; int child_pid; pipe(pipes); printf("I have two pipes: %d %d\n", pipes[0], pipes[1]); printf(COLOR_CLEAR); child_pid = fork(); if (child_pid > 0) { printf(COLOR_GREEN "I am still a parent, my pid = %d\n"COLOR_CLEAR, getpid()); int f_random = open("/dev/urandom", O_RDONLY); read(f_random, &c, 1); close(f_random); printf(COLOR_GREEN"I read a random number `%d' and send it to pipes[1]\n"COLOR_CLEAR, (int)c); write(pipes[1], &c, 1); c = 0; printf(COLOR_GREEN"Now I wait for a response from pipes[0]\n"COLOR_CLEAR); read(pipes[0], &c, 1); printf(COLOR_GREEN "I have read number `%d'. Good night, sweet pipes.\n"COLOR_CLEAR, (int)c); } else { printf(COLOR_RED "I am a child, my pid = %d\n" COLOR_CLEAR, getpid()); read(pipes[0], &c, 1); printf(COLOR_RED "I read a number `%d' from pipes[0]\n"COLOR_CLEAR, (int)c); printf(COLOR_RED "Then I slowly divide it by 2 and send it to pipes[1]\n"COLOR_CLEAR); c /= 2; sleep(5); write(pipes[1], &c, 1); printf(COLOR_RED "And that's my farewell.\n"COLOR_CLEAR); } close(pipes[0]); close(pipes[1]); return 0; }
But usually the child exits without reading a number, and the parent reads the number it has just written:
$ ./pipe Let the story begin I am a parent, my pid = 1545 I have two pipes: 3 4 I am still a parent, my pid = 1545 I am a child, my pid = 1546 I read a random number `119' and send it to pipes[1] Now I wait for a response from pipes[0] I have read number `119'. Good night, sweet pipes.
If I trace it with strace, the demo works as it should.
Any idea?
First, wordpress kindly ate indentation and color strings, which makes your code harder to read and try running.
Second, you’ve got race between parent reading from pipe and child starting and reading from pipe. According to pipe(7), pipes always have some internal buffer, and write(2) will not block unless the buffer is full. You’ll have to create two pipes or use other synchronization facilities to make parent and child communicate reliably.
1. That’s why I prefer C to Python 😉 Spaces and newlines are too volatile.
2. Exactly! I was waiting for two key phrases from my readers: “race condition” and “single buffer”.
Thank you for reading my blog, Ivan!