# HG changeset patch # User Markus Bröker # Date 1254041809 -7200 # Node ID 244356bc3a2015afdadeb9cae7db4e1fae3142a5 # Parent a540a842ddef5b975ae94514a6dbcd405ba9aaa5 Pipes and COPY-ON-WRITE In this example, every forked process gets its own copy of the countervariable i through copy-on-write. committer: Markus Bröker diff --git a/Makefile b/Makefile --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ CC = gcc -g -ggdb $(PROF) CPP = g++ -g -ggdb $(PROF) - CFLAGS = -Wall -O2 -Iinclude -ansi + CFLAGS = -Wall -O2 -Iinclude #-ansi RM = rm -f FIND = find @@ -67,6 +67,7 @@ TARGET += numbers TARGET += nearest TARGET += cppdatabase +TARGET += pipe .SUFFIXES: .c .cc .asm @@ -322,6 +323,11 @@ @echo Linking $<... @$(CPP) -Wall -O2 -g -ggdb $< -o $@ +pipe: pipe.o + @echo Linking $<... + @$(CC) -Wall -O2 -g -ggdb $< -o $@ + + .PHONY: beauty clean uninstall clean: diff --git a/pipe.c b/pipe.c new file mode 100644 --- /dev/null +++ b/pipe.c @@ -0,0 +1,69 @@ +/** + * pipe.c + * Copyright (C) 2009 Markus Broeker + * + */ + +#include +#include +#include +#include +#include + +#define MAX 50 + +int main (int argc, char **argv) +{ + int tube[2]; + int i, status, count = 0; + + pid_t pid; + + char buffer[80]; + + for (i = 0; i < MAX; i++) { + if (pipe (tube) == -1) { + perror ("PIPE"); + + return EXIT_FAILURE; + } + + pid = fork (); + switch (pid) { + case 0: + // we only want to write + close (tube[0]); + + /** + * copy on write: every forked process gets its own copy of i + * and the magic of synchronization works + */ + for (i = 0; i < MAX; i++) + status = write (tube[1], "MESSAGE FROM SON\n", 17); + break; + + case -1: + printf ("ERROR"); + break; + + default: + printf ("Son started as pid %d\n", pid); + + // we only want to read... + close (tube[1]); + + FILE *f = fdopen (tube[0], "r"); + assert (f != NULL); + while (fgets (buffer, sizeof (buffer), f) != NULL) { + printf ("FATHER RECEIVED [%4d]: %s", count++, buffer); + } + + if (fclose (f) < 0) + perror ("fclose"); + + printf ("PID [%4d] has finished...\n", wait (&pid)); + } + } + + return EXIT_SUCCESS; +}