SIGBUS mit mmap
-
Hi!
ich arbeite das erste Mal mit mmap und habe Probleme beim Schreiben auf char* array2. array2 ist ein pointer, der über malloc Speicherplatz erhält. Lesen über mmap (array1) funktioniert soweit gut, wenn ich aber auf den mmap-Bereich einer zum Schreiben geöffneten Datei (fp2) zugreifen will, erhalte ich einen SIGBUS (Bus Error) und weiß nicht warum. Ist dies ein Rechteproblem meiner Datei fp2 oder ein Problem von mmap? In der Zeile "array2[j] = u" erhalte ich den Zugriffsfehler d.h. sobald ich das erste Mal schreibe in array2. In meinem Falle ist j=0 innerhalb einer Schleife und u=36 (unsigned char).
.... fp = open(argv[2],O_RDONLY); if(fp == -1) { fprintf(stderr,"Error opening file for reading.\n"); exit(EXIT_FAILURE); } fp2 = open(argv[3],O_RDWR | O_CREAT | O_TRUNC); if(fp2 == -1) { fprintf(stderr,"Error opening file for writing.\n"); exit(EXIT_FAILURE); } .... /* Leseschleife fuer Segmente von jew. 64K */ if(compress == 1) { j=0; w=0; do { array1 = (char*)mmap(0,SEGMENT,PROT_READ,MAP_SHARED,fp,0); if(array1 == MAP_FAILED) { close(fp); close(fp2); fprintf(stderr,"Error mmapping the input file.\n"); exit(EXIT_FAILURE); } array2 = (char*)mmap(0,SEGMENT,PROT_READ | PROT_WRITE,MAP_SHARED,fp2,0); if(array2 == MAP_FAILED) { close(fp); close(fp2); fprintf(stderr,"Error mmapping the output file.\n"); exit(EXIT_FAILURE); } ...... if(u > 0) { if(u < 128) { array2[j] = u; ++j; } .......
Wenn jemand bereits Erfahrung mit mmap hat und mir weiterhelfen kann, das wäre ganz toll. Dank schon einmal.
Gruß
Klemens
-
Hab zwar keine Erfahrung, aber werfe einfach mal in den Raum, dass mmap nur bis zur aktuellen Größe der Datei beschreiben kann.
Ist also die Datei hinter fp2 nur 1 Byte groß, kannst Du nicht viel reinhauen.
Hierzu müsstest Du die Datei zuvor "strecken"Ich klatsch mal ein ungesehenes Schnipselchen aus dem Netz hier hin:
fd = open(DEINEDATEI, O_RDWR | O_CREAT | O_TRUNC, (mode_t)0600); if (fd == -1) { perror("Error opening file for writing"); exit(EXIT_FAILURE); } /* Stretch the file size to the size of the (mmapped) array of ints */ result = lseek(fd, DATEIGRÖßE, SEEK_SET); if (result == -1) { close(fd); perror("Error calling lseek() to 'stretch' the file"); exit(EXIT_FAILURE); } /* Something needs to be written at the end of the file to * have the file actually have the new size. * Just writing an empty string at the current file position will do. * * Note: * - The current position in the file is at the end of the stretched * file due to the call to lseek(). * - An empty string is actually a single '\0' character, so a zero-byte * will be written at the last byte of the file. */ result = write(fd, "", 1); if (result != 1) { close(fd); perror("Error writing last byte of the file"); exit(EXIT_FAILURE); }
Danach wirds mit dem Schreiben evtl. besser klappen.
-
Ok. Danke dir. Die Idee klingt gut.
Ich werde es ausprobieren. Ich arbeite in Segmenten von 64 K d.h. 16 mal Pagesize auf Linux, das was vorher mein fread/fwrite gemacht haben, und möchte bei sehr großen Dateien schneller im IO werden.
-
Das Programm stürzt nicht mehr in dieser Zeile ab. Das war es wohl gewesen. Das Stretching auf Dateebene verhält sich wohl wie malloc für Pointer. Super Forum!
-
Ich konnte jetzt mmap in meinem Kompressor/Dekompressor Programm mit 64K Segmenten realisieren, aber es besteht kein Unterschied zu den Zeiten mit fread/fwrite. Ich dachte dass mmap viel schneller auf meinem Linux ist. Muss man für gcc eine spezielle Compileroption benutzen, wenn man mmap effizient einsetzt? Ich benutze lediglich -O3 zur Optimierung. Vielen Dank schon einmal für jeden Hinweis.