Windows核心程式設計:第10章 同步裝置IO與非同步裝置IO

gongluck發表於2018-07-19

Github

https://github.com/gongluck/Windows-Core-Program.git

//第10章 同步裝置IO與非同步裝置IO.cpp: 定義應用程式的入口點。
//

#include "stdafx.h"
#include "第10章 同步裝置IO與非同步裝置IO.h"

//可提醒IO回撥
VOID WINAPI funComplete(
    _In_    DWORD dwErrorCode,
    _In_    DWORD dwNumberOfBytesTransfered,
    _Inout_ LPOVERLAPPED lpOverlapped
)
{

}

//IO完成埠工作執行緒
DWORD WINAPI workthread(LPVOID lpThreadParameter)
{
    DWORD NumberOfBytesTransferred;
    DWORD CompletionKey;
    OVERLAPPED* pOverlapped;
    BOOL bres = GetQueuedCompletionStatus(lpThreadParameter, &NumberOfBytesTransferred, &CompletionKey, &pOverlapped, INFINITE);
    //GetQueuedCompletionStatusEx可獲取多個IO請求結果
    DWORD dres = GetLastError();

    return 0;
}

int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
                     _In_opt_ HINSTANCE hPrevInstance,
                     _In_ LPWSTR    lpCmdLine,
                     _In_ int       nCmdShow)
{
    //開啟(建立)檔案
    HANDLE hFile = CreateFile(TEXT("第10章 同步裝置IO與非同步裝置IO.cpp"), GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ, nullptr, OPEN_EXISTING, 0, nullptr);
    if (hFile == INVALID_HANDLE_VALUE)
    {
        MessageBox(nullptr, TEXT("開啟檔案失敗!"), TEXT("error"), MB_OK);
        return 0;
    }

    //檔案型別
    DWORD dres = GetFileType(hFile);
    //dres == FILE_TYPE_DISK

    //檔案大小
    LARGE_INTEGER li;
    BOOL bres = GetFileSizeEx(hFile, &li);//邏輯大小
    li.LowPart = GetCompressedFileSize(TEXT("第10章 同步裝置IO與非同步裝置IO.cpp"), (DWORD*)&li.HighPart);//物理大小

    //檔案指標
    li.QuadPart = 0;
    bres = SetFilePointerEx(hFile, li, nullptr, FILE_END);
    bres = SetFilePointerEx(hFile, li, &li, FILE_CURRENT);
    bres = SetEndOfFile(hFile);
    li.QuadPart = 0;
    bres = SetFilePointerEx(hFile, li, nullptr, FILE_BEGIN);

    //同步IO
    char* buf = new char[100];
    bres = ReadFile(hFile, buf, 100, &dres, nullptr);
    delete []buf;
    buf = nullptr;

    //重新整理緩衝區
    bres = FlushFileBuffers(hFile);

    //CancelSynchronousIo
    //取消執行緒未完成的同步IO請求

    //關閉檔案
    CloseHandle(hFile);
    hFile = nullptr;

    //非同步IO
    HANDLE hFile2 = CreateFile(TEXT("第10章 同步裝置IO與非同步裝置IO.cpp"), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, nullptr);
    OVERLAPPED ol;
    ol.Offset = 1024;
    ol.OffsetHigh = 0;
    ol.hEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr);
    char* buf2 = new char[1024];
    bres = ReadFile(hFile2, buf2, 1024, nullptr, &ol);//非同步方式總是返回FALSE
    dres = GetLastError();
    switch (dres)
    {
    case ERROR_IO_PENDING:
        //IO請求新增成功
        //WaitForSingleObject(hFile2, INFINITE);
        WaitForSingleObject(ol.hEvent, INFINITE);
        break;
    case ERROR_INVALID_USER_BUFFER:
    case ERROR_NOT_ENOUGH_MEMORY:
        break;
    case ERROR_NOT_ENOUGH_QUOTA:
        break;
    default:
        break;
    }

    //取消佇列中的IO請求
    //bres = CancelIo(hFile2);
    bres = CancelIoEx(hFile2, &ol);
    //bres = CancelIoEx(hFile2, nullptr);
    //bres = CloseHandle(hFile2);

    if (ol.hEvent != nullptr)
    {
        CloseHandle(ol.hEvent);
        ol.hEvent = nullptr;
    }

    //可提醒IO
    OVERLAPPED ol2;
    ol2.Offset = 1024;
    ol2.OffsetHigh = 0;
    ol2.hEvent = nullptr;
    dres = ReadFileEx(hFile2, buf2, 1024, &ol2, funComplete);//回撥函式在同一個執行緒空間
    //置為可提醒狀態
    //APC佇列中只要有一個,執行緒就不會進入睡眠
    dres = SleepEx(INFINITE, TRUE);
    //WaitForSingleObjectEx
    //WaitForMultipleObjectsEx
    //SignalObjectAndWait
    //GetQueuedCompletionStatusEx
    //MsgWaitForMultipleObjectsEx
    dres = GetLastError();//WAIT_IO_COMPLETION

    //手動新增一項到APC佇列
    //可以讓目標執行緒結束睡眠
    dres = QueueUserAPC((PAPCFUNC)funComplete, GetCurrentThread(), NULL);

    //IO完成埠
    HANDLE iocp = CreateIoCompletionPort(hFile2, nullptr, 1, 2);
    HANDLE hts[2];
    for (int i = 0; i < 2; ++i)
        hts[i] = CreateThread(nullptr, 0, workthread, iocp, 0, nullptr);
    bres = PostQueuedCompletionStatus(iocp, 100, 1, &ol); //模擬傳送IO請求完成
    bres = ReadFile(hFile2, buf2, 1024, nullptr, &ol2);
    dres = GetLastError();

    WaitForMultipleObjects(2, hts, TRUE, INFINITE);
    for (int i = 0; i < 2; ++i)
    {
        CloseHandle(hts[i]);
        hts[i] = nullptr;
    }
    CloseHandle(iocp);
    iocp = nullptr;

    CloseHandle(hFile2);
    hFile2 = nullptr;
    delete[]buf2;
    buf2 = nullptr;

    system("pause");
    return 0;
}

相關文章