Windows非同步I/O詳解

來源:互聯網
上載者:User

標籤:Windows;非同步;IO;

當我們對檔案進行讀寫時,線程本該是阻塞的,即線程在等待讀寫操作的結束,這種方式稱為 同步I/O。Windows在系統層為我們提供了一種高效的機制—— 非同步IO
非同步IO提供了這樣一種功能:當你讀取檔案時,讀取函數會立刻返回,讀取任務轉交給系統底層自動處理,這樣檔案的讀取操作就不會阻塞線程。IO操作完成時,由系統發出完成通知。

介紹三種完成通知:
1.直接等待控制代碼(檔案等待對象)
2.等待OVERLAPPED中的hEvent控制代碼(等待事件對象)
3.非同步呼叫(APC調用)

主要函數:CreateFile();ReadFile();WriteFile();
資料成員:OVERLAPPED結構體。

一個控制代碼如果是以非同步IO的方式開啟,那這個控制代碼就具有了兩個特性
1.檔案變為可等待的對象(即具有激發態和非激發態)
2.檔案指標失效(需要通過OVERLAPPED結構體中的的Offect表示讀取或寫入的位置,而不能用SetFilePointer()這樣的函數。)

代碼執行個體:(VS2015控制台)
準備:Debug目錄下建立123.exe並儲存資料

1.直接等待控制代碼
#include "stdafx.h"#include <windows.h>typedef struct _MYOVERLAPPED{    OVERLAPPED ol;    HANDLE hFile;    PBYTE pBuf;    int nIndex;}MYOVERLAPPED,*PMYOVERLAPPED;DWORD WINAPI ThreadProc(LPVOID lParam) {    PMYOVERLAPPED pol = (PMYOVERLAPPED)lParam;    WaitForSingleObject(pol->hFile, INFINITE);    for (int i=0;i<10;i++)    {        printf("%d:%d \n", pol->nIndex,pol->pBuf[i]);    }    printf("讀完了!\n");    return 0;}int main(){    // 1. 非同步IO標記    // 有了這個標記 該檔案就變為可等待的核心對象    // 後面的read write函數就變為非阻塞的    HANDLE hFile = CreateFile(L"123.txt", GENERIC_READ,        FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL| FILE_FLAG_OVERLAPPED, NULL);    // 2. 檔案讀取    PMYOVERLAPPED pol = new MYOVERLAPPED{};    pol->ol.Offset = 0x0;// 從位移0x100這個位置開始讀    // pol->hEvent == NULL; 系統讀取完成後,會把我的hFile變為有訊號狀態    pol->hFile = hFile;    pol->pBuf = new BYTE[0x1000]{};    pol->nIndex =1;    ReadFile(hFile,        pol->pBuf,        0x1000,        NULL,//實際讀取的個數,由OVERLAPPED結構體指定        (LPOVERLAPPED)pol);    HANDLE hThread = CreateThread(NULL, NULL, ThreadProc, pol, NULL, NULL);    PMYOVERLAPPED pol2 = new MYOVERLAPPED{};    pol2->ol.Offset = 0x0;// 從位移0x100這個位置開始讀                           // pol->hEvent == NULL; 系統讀取完成後,會把我的hFile變為有訊號狀態    pol2->hFile = hFile;    pol2->pBuf = new BYTE[0x1000]{};    pol2->nIndex = 2;    ReadFile(hFile,        pol2->pBuf,        0x1000,        NULL,//實際讀取的個數,由OVERLAPPED結構體指定        (LPOVERLAPPED)pol2);    HANDLE hThread2 = CreateThread(NULL, NULL, ThreadProc, pol2, NULL, NULL);    // ......幹其他事    WaitForSingleObject(hThread, INFINITE);    WaitForSingleObject(hThread2, INFINITE);    return 0;}
2.等待事件對象
#include "stdafx.h"#include <windows.h>typedef struct _MYOVERLAPPED {    OVERLAPPED ol;    HANDLE hFile;    PBYTE pBuf;    int nIndex;}MYOVERLAPPED, *PMYOVERLAPPED;DWORD WINAPI ThreadProc(LPVOID lParam) {    PMYOVERLAPPED pol = (PMYOVERLAPPED)lParam;    printf("開始等待......\n");    WaitForSingleObject(pol->ol.hEvent, INFINITE);    for (int i = 0; i < 10; i++)    {        printf("%d:%02x \n", pol->nIndex, pol->pBuf[i]);    }    printf("讀完了!\n");    return 0;}int main(){    // 1. 非同步IO標記    // 有了這個標記 該檔案就變為可等待的核心對象    // 後面的read write函數就變為非阻塞的    HANDLE hFile = CreateFile(L"..\\Debug\\123.exe", GENERIC_READ,        FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL);    // 2. 檔案讀取    PMYOVERLAPPED pol = new MYOVERLAPPED{};    pol->ol.Offset = 0x100;// 從位移0x100這個位置開始讀    pol->ol.hEvent = CreateEvent(NULL,NULL,FALSE,NULL); //系統讀取完成後,會把我的hFile變為有訊號狀態    pol->hFile = hFile;// 被無視    pol->pBuf = new BYTE[0x1000]{};    pol->nIndex = 1;    ReadFile(hFile,        pol->pBuf,        0x1000,        NULL,//實際讀取的個數,由OVERLAPPED結構體指定        (LPOVERLAPPED)pol);    HANDLE hThread = CreateThread(NULL, NULL, ThreadProc, pol, NULL, NULL);    PMYOVERLAPPED pol2 = new MYOVERLAPPED{};    pol2->ol.Offset = 0x200;// 從位移0x100這個位置開始讀    pol2->ol.hEvent = CreateEvent(NULL, NULL, FALSE, NULL); //系統讀取完成後,會把我的hFile變為有訊號狀態    pol2->hFile = hFile;// 被無視    pol2->pBuf = new BYTE[0x1000]{};    pol2->nIndex = 2;    ReadFile(hFile,        pol2->pBuf,        0x1000,        NULL,//實際讀取的個數,由OVERLAPPED結構體指定        (LPOVERLAPPED)pol2);    HANDLE hThread2 = CreateThread(NULL, NULL, ThreadProc, pol2, NULL, NULL);    // ......幹其他事    WaitForSingleObject(hThread, INFINITE);    WaitForSingleObject(hThread2, INFINITE);    return 0;}
3.非同步呼叫(APC調用)非同步呼叫提供了這樣一個機制:你可以在讀取檔案或者寫入檔案的時候,提供一個回呼函數,當讀寫任務完成時,就會調用這個回呼函數。
#include "stdafx.h"#include <windows.h>typedef struct _MYOVERLAPPED {    OVERLAPPED ol;    HANDLE hFile;    PBYTE pBuf;    int nIndex;}MYOVERLAPPED, *PMYOVERLAPPED;// 提交任務的線程處理,其他線程看著VOID CALLBACK FileIOCompletionRoutine(    _In_    DWORD        dwErrorCode,    _In_    DWORD        dwNumberOfBytesTransfered,    _Inout_ LPOVERLAPPED lpOverlapped) {    PMYOVERLAPPED pol = (PMYOVERLAPPED)lpOverlapped;    for (int i = 0; i < 10; i++)    {        printf("%d:%02x \n", pol->nIndex, pol->pBuf[i]);    }    printf("讀完了!\n");}int main(){    // 1. 非同步IO標記    // 有了這個標記 該檔案就變為可等待的核心對象    // 後面的read write函數就變為非阻塞的    HANDLE hFile = CreateFile(L"..\\Debug\\123.exe", GENERIC_READ,        FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL);    // 2. 檔案讀取    PMYOVERLAPPED pol = new MYOVERLAPPED{};    pol->ol.Offset = 0x100;// 從位移0x100這個位置開始讀    // hEvent被無視   hFile也被無視    //pol->ol.hEvent = CreateEvent(NULL, NULL, FALSE, NULL); //系統讀取完成後,會把我的hFile變為有訊號狀態    pol->hFile = hFile;// 被無視    pol->pBuf = new BYTE[0x1000]{};    pol->nIndex = 1;    ReadFileEx(hFile,        pol->pBuf,        0x1000,        (LPOVERLAPPED)pol,        FileIOCompletionRoutine);// 完成後直接調用該回呼函數,不用等待檔案控制代碼/事件對象    PMYOVERLAPPED pol2 = new MYOVERLAPPED{};    pol2->ol.Offset = 0x200;// 從位移0x100這個位置開始讀    //pol2->ol.hEvent = CreateEvent(NULL, NULL, FALSE, NULL); //系統讀取完成後,會把我的hFile變為有訊號狀態    //pol2->hFile = hFile;// 被無視    pol2->pBuf = new BYTE[0x1000]{};    pol2->nIndex = 2;    ReadFileEx(hFile,        pol2->pBuf,        0x1000,        (LPOVERLAPPED)pol2,        FileIOCompletionRoutine);    // FileIOCompletionRoutine有系統調用    // 哪個線程執行該函數呢    // 哪個線程read/write 哪個線程執行    // ......幹其他事    // 忙完了  想起來還有兩個函數等著我呢    // CPU檢測到當前線程的APC隊列裡有函數需要執行    // 就去執行該函數,執行完返回    // 只有當第2個參數是TRUE才去執行    SleepEx(200, TRUE);//  WaitForSingleObjectEx()    return 0;}

Windows非同步I/O詳解

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.