异步I/O(1)使用设备内核对象

来源:互联网 发布:淘宝神兽金刚玩具 编辑:程序博客网 时间:2024/06/06 00:42

进行异步I/O的四种方式
1. 使用设备内核对象
2. 使用事件内核对象使用事件内核对象
3. 可提醒I/O可提醒I/O
4. I/O完成端口I/O完成端口

异步I/O的操作过程:
当我们使用异步I/O操作时,我们的程序不会卡死在文件操作的地方.如当我们使用CreateFile打开一个个文件时,它会给操作系统发送一个打开文件的请求然后就直接返回,不会等待文件打开是否成功.此时我们可以进行其他的操作.在操作系统将文件成功打开之后就会发送一个通知.然后就可以去处理文件打开之后的操作.

在进行异步操作时,首先需要将CreateFile的dwFlagsAndAttributes参数设置为FILE_FLAG_OVERLAPPED

在进行异步操作的时候需要使用一个结构体

typedef struct _OVERLAPPED {    ULONG_PTR Internal;//保存请求的错误码    ULONG_PTR InternalHigh;//传输成功的字节数    union {        struct {//文件开始读写的偏移位置            DWORD Offset;            DWORD OffsetHigh;        } DUMMYSTRUCTNAME;        PVOID Pointer;    } DUMMYUNIONNAME;    HANDLE  hEvent;//事件内核对象,在I/O操作完成之后被激发} OVERLAPPED, *LPOVERLAPPED;

异步I/O的基本操作

//一个文件类class MyFile{public:    MyFile(const WCHAR *filePath = L"");    ~MyFile();    BOOL OpenFile(        _In_      DWORD dwDesiredAccess = GENERIC_READ | GENERIC_WRITE,        _In_      DWORD dwShareMode = FILE_SHARE_READ,        _In_      DWORD dwCreationDisposition = OPEN_EXISTING,        _In_      DWORD dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL,        _In_opt_  LPSECURITY_ATTRIBUTES lpSecurityAttributes = nullptr,         _In_opt_  HANDLE hTemplateFile = nullptr    );    WCHAR *SetFilePath(const WCHAR *filePath);    const WCHAR *GetFilePath()const;    const LONGLONG GetFileSize()const;    const HANDLE GetHandle()const;private:    HANDLE m_hFile;    WCHAR *m_filePath;};MyFile::MyFile(const WCHAR *filePath):m_hFile(INVALID_HANDLE_VALUE){    SetFilePath(filePath);}MyFile::~MyFile(){    delete[]m_filePath;    if (m_hFile != INVALID_HANDLE_VALUE)        CloseHandle(m_hFile);}BOOL MyFile::OpenFile(    _In_      DWORD dwDesiredAccess,    _In_      DWORD dwShareMode,    _In_      DWORD dwCreationDisposition,    _In_      DWORD dwFlagsAndAttributes,    _In_opt_  LPSECURITY_ATTRIBUTES lpSecurityAttributes,    _In_opt_  HANDLE hTemplateFile){    BOOL bRet = TRUE;    m_hFile = CreateFileW(m_filePath, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);    if(m_hFile == INVALID_HANDLE_VALUE)    {        bRet = FALSE;        throw WinException(GetLastError());    }    return bRet;}WCHAR* MyFile::SetFilePath(const WCHAR* filePath){    SIZE_T strLen = wcslen(filePath) + sizeof(WCHAR);    m_filePath = new WCHAR[strLen];    wcscpy_s(m_filePath, strLen, filePath);    return m_filePath;}const WCHAR* MyFile::GetFilePath() const{    return m_filePath;}const LONGLONG MyFile::GetFileSize()const{    LARGE_INTEGER large_integer = { 0 };    GetFileSizeEx(m_hFile, &large_integer);    return large_integer.QuadPart;}const HANDLE MyFile::GetHandle() const{    return m_hFile;}
//一个异常类class WinException{public:    WinException(DWORD dwErrorCode);    ~WinException();    const WCHAR *What()const;private:    DWORD m_dwErrorCode;    WCHAR *m_strErrorMsg;};WinException::WinException(DWORD dwErrorCode):m_dwErrorCode(dwErrorCode){    FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, nullptr, m_dwErrorCode, 0, (LPWSTR)(&m_strErrorMsg), 0, nullptr);}WinException::~WinException(){    LocalFree(m_strErrorMsg);}const WCHAR* WinException::What() const{    return m_strErrorMsg;}
//调用过程int main(){    MyFile clsFile(L"a.txt");    clsFile.OpenFile(GENERIC_READ, 0, OPEN_ALWAYS, FILE_FLAG_OVERLAPPED);    BYTE buffer[MAXBYTE] = { 0 };    OVERLAPPED overlapped = { 0 };    BOOL bRet = ReadFile(clsFile.GetHandle(), buffer, MAXBYTE, nullptr, &overlapped);    DWORD dwError = GetLastError();    if(!bRet && dwError == ERROR_IO_PENDING)    {        WaitForSingleObject(clsFile.GetHandle(), 10);        std::cout << buffer;    }    return 0;}
阅读全文
1 0