threads lesen und schreiben selbe datei

baerbelita

Grünschnabel
Hallo,

ich habe folgendes Problem: ich habe eine datei (File *toSend = fopen("test","a+")), in die ein thread schreibt (putc(outbfr,toSend)) und aus der ein anderer thread "gleichzeitig" liest (fread(buffer,1,BUFFER_SIZE,toSend)).

fread scheint nur leider nichts zu lesen, da es mir immer nur 0 zurueck gibt. Ich vermute, dass ich ein Zeigerproblem habe, aber ich weiss nicht, wie ich es loesen kann. Wisst ihr weiter?

Ich programmiere in C, und benutze den gcc als Compiler.
 
Zuletzt bearbeitet:
Hi.

Wenn du von mehreren Threads auf eine Resource zugreifen willst mußt du den Zugriff normalerweise synchronisieren. Da solltest du dir mal Mutex (http://de.wikipedia.org/wiki/Mutex) anschauen.

Außerdem heißt es im C Standard das wenn man bei Dateien die im Update Modus geöffnet wurden zwischen einem read und einem write erst entweder ein seek bzw. ein flush machen muß.

Wenn du die pthreads verwendest solltest du dir evtl. auch mal die Dokumentation über Synchronisation anschauen (http://yolinux.com/TUTORIALS/LinuxTutorialPosixThreads.html#SYNCHRONIZATION)

Gruß
 
Wenn die Datei nur für die Kommunikation zwischen den Threads da ist, solltest Du das evtl. besser mit Pipes machen.
 
Hallo noch mal,

ich habe gelesen, dass beim Schliessen einer Datei, Bufferinhalte auch festgeschrieben werden. Deswegen benutze ich im Code weiter unten kein fflush(), aber vielen Dank fuer den Tip!
Ich werde das mit der Datei auch aendern muessen (stattdessen Speicher verwenden), aber ich bin noch neu in C Programmierung und wollte es erst mal "anschaulich" fuer mich ausprobieren.

Momentan versuche ich folgendes: Daten werden in eine Datei geschrieben (toReadFrom) und von einem Thread ausgelesen und in eine andere Datei (toWriteTo) geschrieben. Im Prinzip kopiere ich also die Datei toReadFrom stueckchenweise mittels des Threads. Mein Problem ist, dass die Datei toReadFrom fehlerfrei geschrieben wird, die Datei toWriteTo jedoch Fragmente von toReadFrom doppelt enthaelt und somit keine Kopie ist. Ich schicke mal den Code mit, vielleicht findet ihr meinen Fehler.

Mein Program schreibt, sobald ein 8 bit buffer voll ist, den Bufferinhalt in eine Datei. Hierfuer locked es das tmpFileMutex, oeffnet die Datei, schreibt,schliesst die Datei und gibt das tmpFileMutex wieder frei. Ausserdem, falls die Anzahl der neu geschriebenen Bits der Anzahl von Bits entspricht, die der Thread verarbeiten moechte, weckt es diesen auf (bzw. wenn es das letzte Mal in die Datei schreibt und vielleicht weniger Daten hat, als der Thread verarbeiten moechte).
Code:
if (outcnt==0) /* 8 bit buffer full */ {
     
     pthread_mutex_lock(&tmpFileMutex); 
     toReadFrom = fopen("toReadFrom","ab+");
      
      if (toReadFrom == NULL){ 
           printf("error: kein File geoeffnet\n");
      }
      putc(outbfr,toReadFrom);
      fclose(toReadFrom);
      writtenCount = writtenCount + 8; // to inform the thread
      writtenBytes = writtenBytes +8;  // for stopping the thread
     
      if (writtenCount == (BUFFER_SIZE*8) || calledLastTime) {
     
        sem_post(&bytesToSendCount);
     	writtenCount = 0;
      }
      pthread_mutex_unlock(&tmpFileMutex); 
}
Der Thread wartet darauf, dass er aufgeweckt wird und locked dann das mutex. Er oeffnet die Datei, von der er lesen moechte und die Datei, in die er schreiben will. Um Daten nicht doppelt zu schreiben, gibt es pointercount, das hochgezaehlt wird und somit immer an der "Nahtstelle" zu den noch nicht gelesenen Daten steht. Kann er seinen Buffer mit neuen Daten fuellen, schreibt er diesen in die andere Datei und zaehlt den pointercount hoch. Anschliessend schliesst er die Dateien und unlocked das mutex.

Code:
while (true) {
  sem_wait(&bytesToSendCount);
  pthread_mutex_lock(&tmpFileMutex);
  toReadFrom = fopen("toReadFrom","rb"); 
  
  if (toReadFrom == NULL) {
  	printf("error: kein File geoeffnet\n");
  }
  toWriteTo = fopen("toWriteTo", "ab+");
  
  if (toWriteTo == NULL) {
  	printf("error: kein File geoeffnet\n");
  }
  fseek(toSend, pointercount, SEEK_SET);
  bytes_read = fread(buffer, 1, BUFFER_SIZE, toReadFrom);
  
  if (bytes_read > 0) {
    
    fwrite(buffer,1,BUFFER_SIZE, toWriteTo);
    writtenBits = writtenBits + bytes_read * 8;
    pointercount = ftell(toSend);
    //  pointercount = pointercount + 8*BUFFER_SIZE; ?
    /* beide Versionen haben nicht geklappt */
    }
  fclose(toSend);
  fclose(toWrite);
  pthread_mutex_unlock(&tmpFileMutex);
    
  if (writtenBits == readBits && finish) {
    
	// finish wird auf true gesetzt, sobald das obige Codefragment das letzte mal
	// aufgerufen wurde
    	break;
    }     
}
 
Zurück