C lesen und schreiben in eine pipe

Mark.G.

Ensign
Registriert
Okt. 2008
Beiträge
249
Also, folgendes "Prog" soll aus einer datei lesen, den inhalt in eine pipe schreiben, ihn wieder auslesen und in eine neue datei schreiben. Leider bleibt das prog nach dem
Code:
printf("hier\n");
stehen. Wenn ich die pipe nicht close sondern durchwegs offen lasse, dann macht er die while aber bleibt da nach dem letzten durchgang stehen. (geht also nicht aus dem while raus, macht aber auch nichts mehr)

Code:
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>
#include <string.h>
#include <unistd.h>
#include <sys/wait.h>
#include <time.h>

int main (int argc, char* argv[])
{
    short ipara=0, opara=0, c=0;
    int mkpipe=-1;
    FILE *pipeleft, *inputF, *outputF;
    char inputpath[256],outputpath[256],line[1001], buffer[1001];
    char pipename[256];
    int timestamp = 0;
    while( (c = getopt(argc, argv, "i:o:")) != -1 )
    {
        switch (c)
        {
            case 'i':   ipara++;
                        strcpy(inputpath,optarg);
                        break;
            case 'o':   opara++;
                        strcpy(outputpath,optarg);
                        break;
            default:    return 1;
        }
        if((ipara || opara)!= 1) return 1;
    
    }
    printf("Vater\n");
    timestamp = time(NULL);
    sprintf(pipename,"%d",timestamp);
    if ((mkpipe=(mkfifo(pipename, 0660))) == -1)
    {
        fprintf(stderr,"myCopy: Error creating fifo pipileft!\n");
        return 1;
    }
    inputF = fopen (inputpath, "r"); //oeffnet datei zum lesen
    if (inputF == NULL) //falls file nicht vorhanden dann fehler
    {
        printf("myCopy: cannot open input file: %s\n",inputpath);
        return 1;
    }
    if ((pipeleft = fopen(pipename, "w+")) == NULL)
    {
            printf("myCopy: cannot open pipeleft\n");
            return 1;
    }
    while(fgets(line, 1000, inputF) != NULL) //speichere string
    {
        fputs(line, pipeleft);
    }
    fclose (inputF); // schließe outputF
    if (fclose(pipeleft) == EOF)
    {
            printf("myCopy: cannot close pipeleft\n");
            return 1;
    }
    printf("Ende Vater\n");


    printf("Kind\n");
    if ((pipeleft = fopen(pipename, "w+")) == NULL)
    {
            printf("myCopy: cannot open pipeleft\n");
            return 1;
    }
    outputF = fopen (outputpath, "w+"); // oeffnet datei zum schreiben (& lesen)
    if(outputF == NULL) //falls file nicht vorhanden dann fehler
    {
        printf("myCopy: cannot open output file: %s (line 55)\n",outputpath);
        return 1;
    }
    printf("hier\n");
    while(fgets(buffer, 1000, pipeleft) != NULL) //speichere string 
    {
        fputs (buffer,outputF); //schreibe in outputF
        printf("hier1\n");
    }
    fclose (outputF); // schließe outputF
    if (fclose(pipeleft) == EOF)
    {
        printf("myCopy: cannot close pipeleft (line 62)");
        return 1;
    }
    printf("Ende Kind\n");

    return 0;
}
 
Zuletzt bearbeitet:
Du liest einen 1000 Bytes Block und wenn weniger Daten in der Pipe sind, blockiert der read bis die 1000 Bytes
voll sind. Ich würde vorschlagen, kleinere Blöcke zu lesen und zwischendurch zu prüfen, ob alle Daten da sind.

Außerdem meldet man Fehler auf stderr und lässt main() EXIT_SUCCESS bzw EXIT_FAILURE zurückgeben. Um der
Portabilität willen.
 
Das kann so nicht funktionieren, weil Du nacheinander in eine named Pipe (also FIFO Datei) schreibst und dann liest. Nach dem Schreiben schliesst Du die FIFO Datei in der Hoffnung, das die Daten dann beim Lesen noch drin sind. Das ist aber nicht der Fall. FIFO's verhalten sich wie normale Pipes, die man zwischen zwei Prozessen aufbaut, nur das FIFO's eben Dateien sind. Kurz gesagt funktioniert das so:

Ein Prozess macht eine FIFO nur zum Schreiben auf und schreibt hinein. Der Systemaufruf zum Schreiben (write) bleibt solange haengen, bis ein Prozess die FIFO nur zum Lesen oeffnet und daraus liest. Wenn der schreibende Prozess dann die FIFO schliesst, bekommt der lesende Prozess EOF zurueck. (Ist der lesende Prozess zuerst da, bleibt der Systemaufruf zum Lesen (read) haengen, bis geschrieben wird.)

Der Ansatz mit "Kind" und "Vater" im Programm war schon richtig. Du hast nur vergessen, einen Kindprozess zu erzeugen. Ich habe das Programm mal korrigiert. (Wieviel Byte Du auf einmal durch die FIFO Datei schiebst, ist dabei unerheblich.)

Code:
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>
#include <string.h>
#include <unistd.h>
#include <sys/wait.h>
#include <time.h>
#include <unistd.h>
#include <errno.h>

int main (int argc, char* argv[])
{
    short ipara=0, opara=0, c=0;
    int mkpipe=-1;
    FILE *pipeleft, *inputF, *outputF;
    char inputpath[256],outputpath[256],line[1001], buffer[1001];
    char pipename[256];
    int timestamp = 0;
    pid_t pid;
    while( (c = getopt(argc, argv, "i:o:")) != -1 )
    {
        switch (c)
        {
            case 'i':   ipara++;
                        strcpy(inputpath,optarg);
                        break;
            case 'o':   opara++;
                        strcpy(outputpath,optarg);
                        break;
            default:    return 1;
        }
        if((ipara || opara)!= 1) return 1;

    }

    timestamp = time(NULL);
    sprintf(pipename,"%d",timestamp);
    if ((mkpipe=(mkfifo(pipename, 0660))) == -1)
    {
        fprintf(stderr,"myCopy: Error creating fifo pipileft!\n");
        return 1;
    }

    if ((pid = fork()) < 0)
    {
       fprintf(stderr, "Fehler bei fork. %s\n", strerror(errno));
       return 1;
    }
    else if (pid != 0) // Vaterprozess
    {
       printf("Vater\n");
       inputF = fopen (inputpath, "r"); //oeffnet datei zum lesen
       if (inputF == NULL) //falls file nicht vorhanden dann fehler
       {
           printf("myCopy: cannot open input file: %s\n",inputpath);
           return 1;
       }
       if ((pipeleft = fopen(pipename, "w")) == NULL)
       {
               printf("myCopy: cannot open pipeleft\n");
               return 1;
       }
       while(fgets(line, 1000, inputF) != NULL) //speichere string
       {
           fputs(line, pipeleft);
       }
       fclose (inputF); // schließe outputF
       if (fclose(pipeleft) == EOF)
       {
           printf("myCopy: cannot close pipeleft\n");
           return 1;
       }
       printf("Ende Vater\n");
    }
    else // Kindprozess
    {
       printf("Kind\n");
       if ((pipeleft = fopen(pipename, "r")) == NULL)
       {
           printf("myCopy: cannot open pipeleft\n");
           return 1;
       }
       outputF = fopen (outputpath, "w+"); // oeffnet datei zum schreiben (& lesen)
       if(outputF == NULL) //falls file nicht vorhanden dann fehler
       {
           printf("myCopy: cannot open output file: %s (line 55)\n",outputpath);
           return 1;
       }
       printf("hier\n");
       while(fgets(buffer, 1000, pipeleft) != NULL) //speichere string
       {
           fputs (buffer,outputF); //schreibe in outputF
           printf("hier1\n");
       }
       fclose (outputF); // schließe outputF
       if (fclose(pipeleft) == EOF)
       {
           printf("myCopy: cannot close pipeleft (line 62)");
           return 1;
       }
       printf("Ende Kind\n");
    }

    return 0;
}
 
Zurück
Oben