Kommunikation über Named Pipes

Es gibt Aufgaben, daß die Ausgabe eines Programms (sagen wir Prg1) direkt als Eingabe eines anderen Programms (Prg2) verwendet und nicht als File gespeichert werden soll. Ein Beispiel: Prg1 generiert Daten, die als geheim eingestuft sind (z.B. Paßwörter, PINs, etc.) und leitet sie nach stdout. Prg2 empfängt diese Daten über stdin und bearbeitet weiter (z.B. verschlüsselt). Beide Prozesse sind über eine Pipe verbunden.

1) Der Aufruf würde dann etwa so aussehen:

Prg1 | Prg2

2) Eine andere Möglichkeit wäre, beide Prozesse über eine Named Pipe kommunizieren zu lassen:

# Eine Named Pipe anlegen (der Name spielt keine Rolle).
mkfifo /Pfad/Prg1.to.Prg2.fifo
 
# Den schreibenden Prozeß im Hintergrund starten, die Pipe wird zum Schreiben geöffnet.
Prg1 > /Pfad/Prg1.to.Prg2.fifo &
 
# Der schreibende Prozeß wird solange angehalten, bis die Pipe durch den lesenden Prozeß zum Lesen geöffnet wird.
Prg2 < /Pfad/Prg1.to.Prg2.fifo
 
# Jetzt laufen beide Prozesse, die Daten werden über die Pipe geschaufelt.
 
# Als die Kommunikation abgeschlossen ist, soll die Pipe wieder gelöscht werden.
rm /Pfad/Prg1.to.Prg2.fifo

3) Es gibt aber Situationen, daß es sinnvoller erscheint, alle in der 2. Möglichkeit erwähnten Schritte direkt in das Prg1 zu kapseln. Das hat Vorteil, daß:

Ein Programmbeispiel für die 3. Variante könnte so aussehen:

{
	int rc = 0; // ReturnCode
	FILE *pipeFIFO = NULL;
	char pipeName [] = "/tmp/eineTestPipe.fifo";
	char runStr [1024];
 
	memset(runStr, '\0', sizeof(runStr));
 
	// Teil 1: Vorbereitung
 
	if (!rc) remove(pipeName); // Evtl. bereits vorhandene Named Pipe wird vorsorglich entfernt.
 
	if (!rc)
	{
		if ((rc = mkfifo(pipeName, 0666)) == 0) printf("Named Pipe %s wurde angelegt.\n", pipeName); // Named Pipe anlegen.
		else printf("Named Pipe %s konnte nicht angelegt werden.\n", pipeName);
	} // if
 
	if (!rc)
	{
		sprintf(runStr, "cat %s &", pipeName); // Aufruf des Lese-Programms (im Text Prg2) vorbereiten.
		if ((rc = system(runStr)) != 0) printf("Prg2: Fehler beim Aufruf vom %s: %s\n", runStr, strerror(errno));
		else printf("Prg2: submitted.\n");
	} // if
 
	// Ab dieser Stelle hat das Leseprogramm die Pipe zum Lesen geöffnet und läuft im Hintergrund.
 
	if (!rc) pipeFIFO = fopen(pipeName, "w"); // Pipe zum Schreiben öffnen
	if (!pipeFIFO) printf("Named Pipe %s konnte nicht geöffnet werden.\n", pipeName); // Fehlermeldung.
	else printf("Named Pipe %s wurde geöffnet.\n", pipeName);
 
	// Teil 2: Datenausgabe in die Pipe
 
	if (pipeFIFO) fprintf(pipeFIFO, "Testausgabe:\nNamed Pipe = [%s], Aufruf von Prg2 = [%s]\n", pipeName, runStr);
 
	// Teil 3: Aufräumen
 
	if (pipeFIFO)
	{
		fflush(pipeFIFO);
		fclose(pipeFIFO); // Die Pipe schließen.
		pipeFIFO = NULL;
		sleep(1); // Vor dem Löschen evtl. kurz abwarten bis der Leseprozeß fertig ist (besser mit wait()).
		if ((rc = remove(pipeName)) != 0) printf("Named Pipe %s konnte nicht gelöscht werden.\n", pipeName); // Fehlermeldung.
	} // if
 
	return rc;
}

Stand: 30.10.2009
: Jürgen Kreick

EOF