So lange die Nachricht (bisher einfach nur ein String) kleiner ist als die Buffergröße der Pipe (oder etwas in der Richtung, kann mich grad nicht erinnern), dann ist die Übertragung über die Pipe atomic - es kommt also genau das auf einmal an, was man reingeschoben hat, oder gar nix (wenn's eine Unterbrechung gab).
Das ist eine gefährlich falsche Annahme. Das "atomisch" bezieht sich nur darauf, dass die write()s von mehreren Prozessen auf die selbe Pipe nicht interleaved werden können, wenn eine bestimmte Nachrichtengröße nicht überschritten wird [1]. Laut POSIX mindestens 512 Byte, bei Linux sogar 4096.
Die Eigenschaft, die du beschreibst -- also dass jedes
read() genau das liefert, was von genau einem
write() geschrieben wurde -- wird nämlich gerade
nicht garantiert. Wenn ein Programm
write(pipe, "foo", 3); write(pipe, "bar", 3); ausführt, dann wird ein darauffolgendes
read(pipe) die 6 Zeichen "foobar" zurückgeben. Oder, um
man 7 pipe [2] zu zitieren:
"The communication channel provided by a pipe is a byte stream: there is no concept of message boundaries.". Ein Artikel [3] beschreibt das Problem (das
scheinbare Funktionieren des Codes) sehr gut, allerdings in Bezug auf TCP.
In Spezialfällen -- also wenn nie zwei write()s in Folge ausgeführt werden, bzw. wenn immer write() und read() im Wechsel aufgerufen werden -- wird deine Lösung funktionieren. Da das aber eine implizite Annahme ist, machst du deinen Code damit weder zukunftssicher noch gut wartbar. Wenn du zum Beispiel mal von Pipes auf TCP/IP umsteigen willst, jemand anderes deinen Code verändert, oder sonst was passiert, kann diese Annahme zu Problemen führen. Ich weiß nicht, ob das in deinem Projekt relevant ist, aber für die Nachwelt möchte ich das hier trotzdem richtig gestellt wissen.
Wie oben bereits geschrieben, gibt es diese Problem nicht, wenn man ein socketpair() mit Typ SOCK_SEQPACKET oder zur Not (nur lokal) SOCK_DGRAM verwendet.
[1]
http://tldp.org/LDP/lpg/node13.html
[2]
http://www.kernel.org/doc/man-pages/onli…an7/pipe.7.html
[3]
http://www.codeproject.com/Articles/3749…Message-Framing
PS: Folgendes Beispiel demonstriert das Problem:
[codefile=pipe.c]#include <unistd.h>
#include <stdio.h>
int main(void) {
int pipefd[2];
pipe(pipefd);
int pid = fork();
if (pid == 0) { // child
write(pipefd[1], "foo", 3);
write(pipefd[1], "bar", 3);
}
else if (pid > 0) { // parent
sleep(1);
char buffer[100];
int count = read(pipefd[0], buffer, 99); // Read from pipe
buffer[count] = '\0'; // Terminate string
printf("Parent received: %s\n", buffer); // Probably print "foobar"
wait(pid); // Clean up child process
}
else { // error
return 1;
}
return 0;
}[/codefile]