2017-05-13 2 views
-1

Windows 겹친 된 IO 시도하고 있지만 그것을 비동기 적으로 작동하도록 얻을 수 없습니다. 아래의 프로그램을 컴파일하고 실행했지만 아무 것도 출력하지 않습니다. 자동으로 완료됩니다. 나는 작은 읽기가 동기가 될 수 있다는 것을 읽었습니다. 그래서 나는 의도적으로 512MB를 읽도록 선택했습니다. ReadFileEx 통화 중Windows 중복 IO 사실 블록

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"); 
    } 

추가 정보로서, 나는 디버거로 코드를 밟아야하고, Overlapped.InternalHigh 값 (Size와 같은 값으로) 업데이트됩니다.

나는 FILE_FLAG_NO_BUFFERING을 추가 ReadFileExReadFile으로, VirtualAllocmalloc를 교체했는데, ReadFile의 반환이 0임을 확인하고 그 GetLastError는 읽기 후 ERROR_IO_PENDING 될했습니다. RAMMap을 사용하여 파일이 캐시에 있었는지 확인했지만 그 중 96KB 밖에 없었습니다.

저는 8GB RAM이 장착 된 Windows 10 (ver. 1703)을 사용하고 있습니다.

+0

때문에 OS는 쉽게 바로 읽을 서비스를 제공 할 수 있다는 결정 ? – EOF

+0

@EOF 전체 512MB + 파일을 심각하게 캐시합니까? 게다가 캐시 된 경우, 내 읽기는 여전히 150ms가 걸립니다 ... 그러면 빠른 리턴을 보장 할 수 없다면 겹쳐지는 부분은 무엇입니까? – Lutopia

+1

이것은 실제로 캐시 관련입니다. FILE_FLAG_OVERLAPPED | FILE_FLAG_NO_BUFFERING' 파일을 열고'PVOID Buffer = VirtualAlloc (0, Size, MEM_COMMIT, PAGE_READWRITE)'(비 캐시 읽기를 위해 정렬되어야 함)을 할당하고 결과를 확인하십시오. ('Ex'없이)'ReadFile'을 더 잘 사용하십시오 -이 경우 마지막 오류가 있으면 false를 반환합니다 - ERROR_IO_PENDING' – RbMm

답변

-2

좋아요. @RbMm 덕분에 모든 것이 작동했습니다.

메모리 할당은 FILE_FLAG_NO_BUFFERING 플래그를 변경하지 않고 ReadFile을 사용하면 효과가있었습니다. ReadFileEx 이후에 SleepEx을 사용해 보았는데 액세스 위반이 0으로 발생하여 lpCompletionRoutine이 필수는 아니지만 @RbMm의 요점을 증명합니다. (내게는 완료 루틴을 원하지 않기 때문에 ReadFile을 사용할 것임을 의미합니다)

무슨 일이 일어 났는지 깨닫는 데 너무 오랜 시간이 걸린 이유는 무엇입니까? 저는 디버거를 너무 많이 신뢰했습니다. 디버거는 IO 프로세스를 멈추지 않았습니다. 즉, 메모리가 여전히 OVERLAPPED 구조 내부에서 업데이트 중이라는 것을 의미합니다. 그것의 꼭대기에 나는 ReadFile이 빨리 돌아올 것으로 예상했지만, 512MB를 읽으려고하면 실제로는 20ms가 걸리며, 소량을 요청하면 훨씬 빠릅니다. 제안 : 완성도를 들어

에 대한

감사합니다 모든 사람, 여기에 작업 프로그램 : 아마 파일이 OS에 의해 캐시

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

당신은'ReadFileEx'를 사용할 수 있습니다 - 최종 결과와 동작에는 전혀 다릅니다 하지만,'lpCompletionRoutine'은 옵션이 아닌 필수 매개 변수입니다. 항상 올바른 (빈 상태 일 수 있음) 루틴을 가리켜 야합니다. 그렇지 않으면 * alertable * 모드에서'ReadFileEx'를 성공적으로 호출 한 후 대기하게되면 충돌이 발생합니다. 그래서'ReadFileEx (File, Buffer, Size, & Overlapped, NULL);은 실수입니다. 데모는 다음 코드'if (Result) SleepEx (INFINITE, TRUE); '를 끝에 추가하십시오. 'GetOverlappedResult'가 끝나면 – RbMm