异步设备IO 《windows核心编程》第10章学习<待续>

 

异步IO操作与同步操作区别:

  1. 在CreateFile里的FILE_FLAG_OVERLAPPED标志
  2. 异步操作函数LPOVERLAPPED参数

接收IO请求完成通知

  1. 触发设备内核对象
    缺点:同一个设备内核对象有可能进行多次读写操作,这样第一个完成这个设备内核对象就会被触发,所以这种方式不可以使用于这种情形
    void Test1()
    {
        HANDLE hFile = ::CreateFile(_T("aaa.txt"),
            GENERIC_READ,
            FILE_SHARE_READ,
            NULL,
            OPEN_EXISTING,
            FILE_FLAG_OVERLAPPED,
            NULL);
        if(!hFile)
        {
            wcout<<L"CreateFile Failed ErroCode:"<<::GetLastError()<<endl;
            return ;
        }
        DWORD dwFileSize = ::GetFileSize(hFile,0);
        wcout<<L"FileSize:"<<dwFileSize<<endl;
        char * pFileContent = new char[10000000];
        DWORD dwReaded = 0;
        OVERLAPPED o_Read = {0};
        DWORD bReadDone = ::ReadFile(hFile,
            pFileContent,
            10000000,
            &dwReaded,
            &o_Read);
        DWORD dwError = ::GetLastError();
        if(!bReadDone && (dwError == ERROR_IO_PENDING))
        {
            WaitForSingleObject(hFile,INFINITE);
            bReadDone = TRUE;
        }
    
        if(bReadDone)
            wcout<<L"I/O Code:"<<o_Read.Internal<<" TransedBytes:"<<o_Read.InternalHigh<<endl;
        else
            wcout<<"Error:"<<::GetLastError()<<endl;
        ::CloseHandle(hFile);
        delete [] pFileContent;
    }
  2. 触发事件内核对象
    void Test2()
    {
        HANDLE hFile = ::CreateFile(_T("aaa.txt"),
            GENERIC_WRITE,
            FILE_SHARE_READ,
            NULL,
            OPEN_EXISTING,
            FILE_FLAG_OVERLAPPED,
            NULL);
        if(!hFile)
        {
            wcout<<L"CreateFile Failed ErroCode:"<<::GetLastError()<<endl;
            return ;
        }
        DWORD dwFileSize = ::GetFileSize(hFile,0);
        wcout<<L"FileSize:"<<dwFileSize<<endl;
        LARGE_INTEGER liDis = {0};
        LARGE_INTEGER liRet = {0};
        ::SetFilePointerEx(hFile,liDis,&liRet,FILE_END);
        wcout<<L"PreWrite File Pos:"<<liRet.LowPart<<endl;
        char * pFileContent = new char[10000000];
        memset(pFileContent,z,10000000);
        DWORD dwReaded = 0;
        OVERLAPPED o_Write = {0};
        o_Write.Offset = liRet.LowPart;
        o_Write.hEvent = ::CreateEvent(NULL,FALSE,FALSE,NULL);
        DWORD bReadDone = ::WriteFile(hFile,
            pFileContent,
            10000000,
            &dwReaded,
            &o_Write);
        DWORD dwError = ::GetLastError();
        if(!bReadDone && (dwError == ERROR_IO_PENDING))
        {
            WaitForSingleObject(o_Write.hEvent,INFINITE);
            bReadDone = TRUE;
        }
    
        if(bReadDone)
            wcout<<L"I/O Code:"<<o_Write.Internal<<" TransedBytes:"<<o_Write.InternalHigh<<endl;
        else
            wcout<<"Error:"<<::GetLastError()<<endl;
        ::CloseHandle(hFile);
        delete [] pFileContent;
    }
  3. 可提醒IO
    void Test3()
    {
        //可提醒IO
        HANDLE hFile = ::CreateFile(_T("aaa.txt"),
            GENERIC_WRITE,
            FILE_SHARE_READ,
            NULL,
            OPEN_EXISTING,
            FILE_FLAG_OVERLAPPED,
            NULL);
        if(!hFile)
        {
            wcout<<L"CreateFile Failed ErroCode:"<<::GetLastError()<<endl;
            return ;
        }
        DWORD dwFileSize = ::GetFileSize(hFile,0);
        wcout<<L"FileSize:"<<dwFileSize<<endl;
        LARGE_INTEGER liDis = {0};
        LARGE_INTEGER liRet = {0};
        ::SetFilePointerEx(hFile,liDis,&liRet,FILE_END);
        wcout<<L"PreWrite File Pos:"<<liRet.LowPart<<endl;
        char * pFileContent = new char[10000000];
        memset(pFileContent,g,10000000);
        DWORD dwReaded = 0;
        OVERLAPPED o_Write = {0};
        o_Write.Offset = liRet.LowPart;
        DWORD bReadDone = ::WriteFileEx(hFile,
            pFileContent,
            10000000,
            &o_Write,
            FileIOCompletionRoutine);
    
        ::CloseHandle(hFile);
        SleepEx(10000,TRUE);
        delete [] pFileContent;
    }

    可提醒IO的优劣:
    (1)由于回调函数的原因,最终不得不把大量信息放在全局变量中。使代码变的更加复杂
    (2)发出请求线程和完成处理必须是同一线程,没有达到线程负载均衡
    可提醒IO相关函数
    (1)QueueUserAPC函数
         a.这个函数允许我们手动增加APC项。
         b.可以强制线程退出等待状态比如WaitForSingleObjectEx 以下是示例代码
    VOID WINAPI APCFunc(ULONG_PTR pvParam)
    {
        //Nothing To Do
    }
    
    UINT WINAPI ThreadFunc(PVOID pvParam)
    {
        wcout<<L"start Wait...."<<endl;
        DWORD dw = ::WaitForSingleObjectEx(pvParam,INFINITE,TRUE);
        if(dw == WAIT_OBJECT_0)
        {
            wcout<<L"Event signaled"<<endl;
            return 0;
        }
        else if(dw == WAIT_IO_COMPLETION)
        {
            wcout<<L"QueueUserApc Forced us out of a wait state"<<endl;
            return 0;
        }
        return 0;
    }
    void Test4()
    {
        //利用QueueUserApc来停止线程等待
        HANDLE hEvent = ::CreateEvent(NULL,FALSE,FALSE,NULL);
        HANDLE hThread = (HANDLE) _beginthreadex(NULL,0,ThreadFunc,hEvent,0,NULL);
        Sleep(5000);
        QueueUserAPC(APCFunc,hThread,NULL);
        WaitForSingleObject(hThread,INFINITE);
        CloseHandle(hThread);
        CloseHandle(hEvent);
    }
  4. I/O完成端口
    待续

异步设备IO 《windows核心编程》第10章学习<待续>

上一篇:开篇!WPF自定义控件(1)——转盘菜单


下一篇:Windows Workflow Foundation技术介绍(基于.NET Framework 4.5)