2017-05-13 4 views
-1

Ich versuche Windows überlappen IO, aber ich kann nicht scheinen, es asynchron zu arbeiten. Ich habe das Programm kompiliert und ausgeführt, aber es druckt nie etwas, es wird nur leise abgeschlossen. Ich habe gelesen, dass kleine Lesevorgänge synchron werden könnten, deshalb habe ich mich bewusst dafür entschieden, 512 MB zu lesen.Windows überlappt IO blockiert tatsächlich

const DWORD Size = 1<<29; // 512MB 
    char* Buffer = (char*)malloc(Size); 
    DWORD BytesRead; 
    OVERLAPPED Overlapped; 
    memset(&Overlapped, 0, sizeof(Overlapped)); 

    HANDLE File = CreateFile("BigFile", GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED, NULL); 
    assert(File!=INVALID_HANDLE_VALUE); 

    DWORD Result = ReadFileEx(File, Buffer, Size, &Overlapped, NULL); // This line takes 150ms according to the debugger 
    assert(Result); 

    while(!GetOverlappedResult(File, &Overlapped, &BytesRead, FALSE)) { 
    printf("Waiting...\n"); 
    } 

Als zusätzliche Information, habe ich den Code in den Debugger tritt, und der Overlapped.InternalHigh Wert aktualisiert wird (mit dem gleichen Wert wie Size) während des ReadFileEx Anrufs.

Ich habe versucht, malloc mit VirtualAlloc, ReadFileEx mit ReadFile ersetzen, das Hinzufügen FILE_FLAG_NO_BUFFERING, und überprüft, dass die Rückkehr von ReadFile 0 war und dass GetLastError wäre ERROR_IO_PENDING nach dem Lesen. Ich habe versucht, mit RAMMap zu sehen, ob die Datei im Cache war, aber nur 96KB davon war da.

Ich verwende Windows 10 (Version 1703) mit 8 GB RAM.

+0

Vielleicht ist die Datei durch das Betriebssystem zwischengespeichert wird, so dass das Betriebssystem entscheidet, dass es leicht die sofort lesen bedienen kann ? – EOF

+0

@EOF Würde es ernsthaft eine ganze 512MB + Datei zwischenspeichern? Plus, wenn es zwischengespeichert wird, dauert mein Lesen immer noch 150ms ... was ist dann der Punkt der Überlappung, wenn es mir keine schnelle Rückkehr garantieren kann? – Lutopia

+1

Dies ist wirklich Cache bezogen. Öffnen Sie die Datei mit 'FILE_FLAG_OVERLAPPED | FILE_FLAG_NO_BUFFERING' und weisen Sie' PVOID Buffer = VirtualAlloc (0, Size, MEM_COMMIT, PAGE_READWRITE) 'zu (es muss für nicht zwischengespeicherte Lesevorgänge ausgerichtet sein) - und prüfen Sie das Ergebnis. und in deinem Fall besser 'ReadFile' verwenden (ohne' Ex') - es wird in diesem Fall mit dem letzten Fehler zu dir zurückkehren - 'ERROR_IO_PENDING' – RbMm

Antwort

-2

Ok Ich habe es funktioniert, alles dank @RbMm.

Die Speicherzuweisung hat nichts geändert, aber das FILE_FLAG_NO_BUFFERING Flag und die Verwendung von ReadFile hat es funktioniert. Ich versuchte mit SleepEx nach ReadFileEx und es warf eine Zugriffsverletzung bei 0, die den Punkt von @RbMm beweist, dass die lpCompletionRoutine ist nicht optional, aber obligatorisch. (Für mich bedeutet das, ich werde ReadFile verwenden, weil ich keine Abschlussroutine haben möchte)

Warum ich so lange brauchte, um zu erkennen, was passierte: Ich vertraute dem Debugger zu viel, offensichtlich brach er ein Der Debugger stoppte den IO-Prozess nicht, was bedeutete, dass der Speicher innerhalb der Struktur OVERLAPPED immer noch aktualisiert wurde, was mich zu der Annahme brachte, dass die Dinge augenblicklich waren. Obendrein erwartete ich ReadFile, um schnell zurückzukehren, aber es dauert tatsächlich 20ms, wenn ich versuche, 512MB zu lesen, es ist viel schneller, wenn ich kleinere Mengen anfordere.

Vielen Dank allen für Ihre Anregungen :)

Der Vollständigkeit halber ist hier das Arbeitsprogramm:

const DWORD Size = 1<<20; 
    char* Buffer = (char*)malloc(Size); 
    DWORD BytesRead; 
    OVERLAPPED Overlapped; 
    memset(&Overlapped, 0, sizeof(Overlapped)); 

    HANDLE File = CreateFile("BigFile", GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING|FILE_FLAG_OVERLAPPED, NULL); 
    assert(File!=INVALID_HANDLE_VALUE); 
    DWORD Result = ReadFile(File, Buffer, Size, NULL, &Overlapped); 
    assert(Result==FALSE && GetLastError()==ERROR_IO_PENDING); 
    while(!GetOverlappedResult(File, &Overlapped, &BytesRead, FALSE)) { 
    printf("Waiting...\n"); 
    } 
+1

Sie können und 'ReadFileEx' verwenden - nicht anders für Endergebnis und Operation Zeit, aber wie ich Entdeckung gerade jetzt 'LpCompletionRoutine' ist obligatorischer Parameter, nicht optional. es muss immer auf die richtige (leere) Routine zeigen. Andernfalls stürzt Ihr System ab, wenn nach dem Aufruf von 'ReadFileEx' im * alertable * Modus gewartet wird. '' ReadFileEx (Datei, Puffer, Größe und Überlappung, NULL); 'ist ein Fehler. für das Demo den nächsten Code 'if (Result) SleepEx (INFINITE, TRUE);' am Ende hinzufügen. nachdem du "GetOverlappedResult" abgeschlossen hast – RbMm