异步IO

作者: MagicalGuy | 来源:发表于2018-10-07 14:29 被阅读0次
    // 08.异步IO-等待文件对象.cpp : 定义控制台应用程序的入口点。
    //
    
    // 每一次文件读取/写入操作,都要创建一个线程,
    // 系统同时运行的线程数是有限的,线程的创建和销毁浪费了大量资源
    // 没有效率
    
    
    #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;
    }
    

    ===========

    // 08.异步IO-等待文件对象.cpp : 定义控制台应用程序的入口点。
    //
    
    #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:%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->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 = 0x200;// 从偏移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;
    }
    

    ====================

    // 08.异步IO-异步过程调用(APC).cpp : 定义控制台应用程序的入口点。
    //
    
    #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;
    }
    

    ============================

    // 08.异步过程调用-完成端口(IOCP).cpp : 定义控制台应用程序的入口点。
    //
    
    #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 =nullptr;
        HANDLE hIOCP = lParam;
        while (TRUE)
        {
            DWORD dwNum = 0;
            ULONG_PTR uCompleteKey = 0;
            BOOL bRet = GetQueuedCompletionStatus(
                hIOCP,// 检查完成端口有没有待处理任务(有任务完成,通知完成端口处理)
                &dwNum,// 实际传输的字节数
                &uCompleteKey,// 哪个设备完成了异步操作
                (LPOVERLAPPED*)&pol,
                INFINITE);
            if (bRet == FALSE && ERROR_ABANDONED_WAIT_0 == GetLastError())
            {
                printf("完成端口被关闭\n");
                return 0;
            }
            if (uCompleteKey == NULL && pol == nullptr)
            {
                PostQueuedCompletionStatus(hIOCP, NULL, NULL, NULL);
                printf("完成端口线程结束!\n");
                return 0;
            }
            for (int i = 0; i < 10; i++)
            {
                
                printf("key:%d,%d:%02x \n", uCompleteKey,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. 创建一个完成端口
        // 先获取核心数
        SYSTEM_INFO si = {};
        GetSystemInfo(&si);
        HANDLE hIOCP = CreateIoCompletionPort(
            INVALID_HANDLE_VALUE,// 创建完成端口,绑定完成端口的时候是文件句柄
            NULL,// 创建完成端口的时候是NULL,绑定的时候是完成端口句柄
            NULL,// 创建完成端口的时候是NULL,绑定的时候是自己设置的一个值,用来区分绑定的文件是哪个
            si.dwNumberOfProcessors);// 完成端口上并行运行的最大线程数,绑定的时候是NULL
        // 3.把完成端口和文件绑定,后面这个文件的所有异步操作的通知都交给完成端口
        CreateIoCompletionPort(
            hFile,
            hIOCP,
            0x12,// 和hFile绑定的值,也可以是hFile本身
            NULL
        );
        // 4. 创建完成端口的服务线程
        for (int i=0;i<si.dwNumberOfProcessors*2;i++)
        {
            CreateThread(NULL, NULL, ThreadProc, hIOCP, NULL, NULL);
        }
        
        // 5. 文件读取
        PMYOVERLAPPED pol = new MYOVERLAPPED{};
        pol->ol.Offset = 0x100;// 从偏移0x100这个位置开始读
        pol->pBuf = new BYTE[0x1000]{};
        pol->nIndex = 1;
        ReadFile(hFile,
            pol->pBuf,
            0x1000,
            NULL,//实际读取的个数,由OVERLAPPED结构体指定
            (LPOVERLAPPED)pol);
    
    
        PMYOVERLAPPED pol2 = new MYOVERLAPPED{};
        pol2->ol.Offset = 0x200;// 从偏移0x100这个位置开始读
        pol2->pBuf = new BYTE[0x1000]{};
        pol2->nIndex = 2;
        ReadFile(hFile,
            pol2->pBuf,
            0x1000,
            NULL,//实际读取的个数,由OVERLAPPED结构体指定
            (LPOVERLAPPED)pol2);
        // ......干其他事
        // 投递一个完成任务
        PostQueuedCompletionStatus(hIOCP, NULL, NULL, NULL);
        system("pause");
        return 0;
    }
    

    相关文章

      网友评论

          本文标题:异步IO

          本文链接:https://www.haomeiwen.com/subject/gzblaftx.html