Ich schreibe einen High-Loaded-Daemon, der auf FreeBSD 8.0 und unter Linux laufen sollte. Der Hauptzweck von Daemon besteht darin, Dateien zu übergeben, die von ihrem Bezeichner angefordert werden. Der Bezeichner wird über die Anfrage in db in den lokalen Dateinamen/Dateigröße konvertiert. Und dann benutze ich sequentielle mmap()
Aufrufe, um Dateiblöcke mit send()
zu übergeben.überprüfe, ob die mmap-Adresse korrekt ist
Es gibt jedoch manchmal nicht übereinstimmende Dateigröße in db und Dateigröße auf Dateisystem (realsize < Größe in db). In dieser Situation habe ich alle realen Datenblöcke gesendet und wenn der nächste Datenblock gemappt wird - mmap gibt keine Fehler zurück, nur die übliche Adresse (ich habe auch die Fehlernummer überprüft, sie ist gleich Null nach mmap). Und wenn der Daemon versucht, diesen Block zu senden, erhält er Segmentierungsfehler. (Dieses Verhalten wird garantiert auf FreeBSD 8.0 amd64 ausgegeben)
Ich benutzte Safe-Check vor dem Öffnen, um die Größe mit Anruf sicherzustellen. Das wirkliche Leben zeigt mir jedoch, dass in seltenen Situationen immer noch segfault auftreten kann.
Also meine Frage gibt es eine Möglichkeit zu überprüfen, ob der Zeiger zugänglich ist, bevor es Dereferenzierung? Wenn ich Core in Gdb geöffnet habe, sagt Gdb, dass die angegebene Adresse außerhalb des Bereichs liegt. Wahrscheinlich gibt es eine andere Lösung, die jemand vorschlagen kann.
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <time.h>
#include <unistd.h>
#define FILENAME "./datafile"
int main()
{
unsigned long i, j;
srand(time(NULL));
unsigned long pagesize = sysconf(_SC_PAGESIZE);
unsigned long basesize = 4 * pagesize;
unsigned long cropsize = 2 * pagesize;
// create 4*pagesize sized file
int f = creat(FILENAME, 0644);
for (i = 0; i < basesize; i++) {
unsigned char c = (unsigned char)rand();
if (write(f, &c, 1) < 1) { perror("write"); break; }
}
close(f);
f = open(FILENAME, O_RDONLY);
// walk trough file
unsigned char xor = 0;
unsigned long offset = 0;
for (j = 0; j < 4; j++) {
// trunc file to 2*pagesize
if (j == 2) truncate(FILENAME, cropsize);
char *data = mmap(NULL, pagesize, PROT_READ, MAP_PRIVATE, f, offset);
if (data == MAP_FAILED) { perror("mmap"); break; }
printf("mmap: %[email protected]%lu for %i\n", pagesize, offset, f);
for (i = 0; i < pagesize; i++) xor ^= data[i];
offset += pagesize;
}
close(f);
return 0;
}
Ich habe Code-Beispiel, das das Problem in Head Post veranschaulicht. Dieser Code emuliert die Erstellung einer Datei und ändert dann die Größe, während sie mit mmap fortgefahren wurde. Auf Linux-System habe ich Bus-Fehler im dritten Schritt, auf FreeBSD gibt es SegFault. – reddot