006 异步IO操作

Posted ☆﹎夜﹎☆

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了006 异步IO操作相关的知识,希望对你有一定的参考价值。

# 异步IO操作

  CreateFile 使用

    VS2015 新建win32 控制台应用程序 WindowsFileDemo

      win32控制台写窗口程序

    需要加入头文件 #include <fileAPI.h> 就可以来使用CreateFile

      分别有 CreateFileA  CreateFileW 窄字节 宽字节

1 HANDLE WINAPI CreateFile(
2     _In_ LPCTSTR lpFileName,
3     _In_ DWORD dwDesiredAccess,
4     _In_ DWORD dwShareMode,
5     _In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes,
6     _In_ DWORD dwCreationDisposition,
7     _In_ DWORD dwFlagsAndAttributes,
8     _In_opt_ HANDLE hTemplateFile
9 );

    //第一个参数 LPCTSTR lpFileName            文件名

    //第二个参数 DWORD dwDesiredAccess           访问权限        

        GENERIC_ALL              所有权限  需要管理员权限 否则可能打开失败
        GENERIC_EXECUTE           文件是否存在
        GENERIC_READ             读
        GENERIC_WRITE             写
        GENERIC_READ | GENERIC_WRITE         组合

    //第三个参数 DWORD dwShareMode                    打开后是否共享 不需要共享的话就写入0

        0

        FILE_SHARE_DELETE

        FILE_SHARE_READ

        FILE_SHARE_WRITE

    //第四个参数 lpSecurityAttributes     一般填写nullpte

         用来设定一个指向包含两个不同但相关的数据成员:一个可选的安全描述符和一个布尔值来决定是否由子进程返回的句柄可以被继承。

    //第五个参数 DWORD dwCreationDisposition   打开方式      

        CREATE_NEW 创建文件;如文件存在则会出错
        CREATE_ALWAYS 创建文件,会改写前一个文件
        OPEN_EXISTING 文件必须已经存在。由设备提出要求
        OPEN_ALWAYS 如文件不存在则创建它
        TRUNCATE_EXISTING 将现有文件缩短为零长度

    //第六个参数 dwFlagsAndAttributesLong, 一个或多个下述常数

        FILE_ATTRIBUTE_ARCHIVE 标记归档属性

        FILE_ATTRIBUTE_COMPRESSED 将文件标记为已压缩,或者标记为文件在目录中的默认压缩方式
        FILE_ATTRIBUTE_NORMAL 默认属性
        FILE_ATTRIBUTE_HIDDEN 隐藏文件或目录
        FILE_ATTRIBUTE_READONLY 文件为只读
        FILE_ATTRIBUTE_SYSTEM 文件为系统文件
        FILE_FLAG_WRITE_THROUGH 操作系统不得推迟对文件的写操作
        FILE_FLAG_OVERLAPPED 允许对文件进行重叠操作
        FILE_FLAG_NO_BUFFERING 禁止对文件进行缓冲处理。文件只能写入磁盘卷的扇区块
        FILE_FLAG_RANDOM_ACCESS 针对随机访问对文件缓冲进行优化
        FILE_FLAG_SEQUENTIAL_SCAN 针对连续访问对文件缓冲进行优化
        FILE_FLAG_DELETE_ON_CLOSE 关闭了上一次打开的句柄后,将文件删除。特别适合临时文件
        也可在Windows NT下组合使用下述常数标记:
        SECURITY_ANONYMOUS,

        SECURITY_IDENTIFICATION,

        SECURITY_IMPERSONATION,

        SECURITY_DELEGATION,

        SECURITY_CONTEXT_TRACKING,

        SECURITY_EFFECTIVE_ONLY

    //第七个参数 HANDLE hTemplateFile

        hTemplateFile,hTemplateFile为一个文件或设备句柄,表示按这个参数给出的句柄为模板创建文件(就是将该句柄文件拷贝到lpFileName指定的路径,然后再打开)。

        它将指定该文件的属性扩展到新创建的文件上面,这个参数可用于将某个新文件的属性设置成与现有文件一样,并且这样会忽略dwAttrsAndFlags。

        通常这个参数设置为NULL,为空表示不使用模板,一般为空。

 

    

    返回值
        如执行成功,则返回文件句柄。
        INVALID_HANDLE_VALUE表示出错,会设置GetLastError。

        即使函数成功,但若文件存在,且指定了CREATE_ALWAYS 或 OPEN_ALWAYS,GetLastError也会设为ERROR_ALREADY_EXISTS

 

  FormatMessage 函数

    ● FormatMessage是一个Windows API函数。它的功能就是将GetLastError函数得到的错误信息(这个错误信息是数字代号)转化成字符串信息的函数。

      DWORD WINAPI FormatMessage (

        DWORD dwFlags, // source and processing options
        LPCVOID lpSource, // message source
        DWORD dwMessageId, // message identifier
        DWORD dwLanguageId, // language identifier
        LPTSTR lpBuffer, // message buffer
        DWORD nSize, // maximum size of message buffer
        va_list *Arguments // array of message inserts
        );

 

       ○ dwFlags

         标志位,决定如何说明lpSource参数,dwFlags的低位制定如何处理换行功能在输出缓冲区,也决定最大宽度的格式化输出行。[1]

       ○ lpSource
        根据dwFlags标志而定

       ○ dwMessageId
        请求的消息的标识符。当dwFlags标志为FORMAT_MESSAGE_FROM_STRING时会被忽略。[1]
       ○ dwLanguageId
        请求的消息的语言标识符。
       ○ LPTSTR lpBuffer
        接收错误信息描述的缓冲区指针。
       ○ nSize
        如果FORMAT_MESSAGE_ALLOCATE_BUFFER标志没有被指定,这个参数必须指定为输出缓冲区的大小,如果指定,这个参数指定为分配给输出缓冲区的最小数。[1]
       ○ Arguments
        保存格式化信息中的插入值的一个数组。

 

  LocalFree 函数
    ○ 功能:释放局部内存对象并使句柄失效
      ● hMem:局部内存对象的句柄,通过函数LocalAlloc或LocalReAlloc返回的。
    ○ 返回值
      ● 函数执行成功返回NULL,否则返回内存对象的句柄,要获得详细错误信息,调用GetLastError函数。

 

  在Windows系统中, 文件大小分为以下两种:

    物理大小
    GetFileSize 已弃用, 因为对于小文件还可以, 但是大文件会超过输出参数的范围
      DWORD WINAPI GetFileSize(
      _In_ HANDLE hFile, //文件句柄
      _Out_opt_ LPDWORD lpFileSizeHigh //文件大小 输出参数
      );
    

    GetFileSizeEx
    占用大小
    BOOL WINAPI GetFileSizeEx(
      _In_ HANDLE hFile, //文件句柄
      _Out_ PLARGE_INTEGER lpFileSize //文件大小 输出参数

 


  ReadFile

    BOOL ReadFile(
            HANDLE hFile,                  //文件的句柄
            LPVOID lpBuffer,                //用于保存读入数据的一个缓冲区
            DWORD nNumberOfBytesToRead,        //要读入的字节数
            LPDWORD lpNumberOfBytesRead,        //指向实际读取字节数的指针
            LPOVERLAPPED lpOverlapped         //结构体指针
            //如文件打开时指定了FILE_FLAG_OVERLAPPED,那么必须,用这个参数引用一个特殊的结构。
            //该结构定义了一次异步读取操作。否则,应将这个参数设为NULL
          );

    

    返回值: 成功返回非0
    同步下, 如果返回值不等于0.

    异步下, 参数5(lpOverlapped)不为NULL时, 当读到文件结尾时, 返回值为FALSE, GetLastError为ERROR_HANDLE_EOF.



  WriteFile
    BOOL WriteFile(
            HANDLE hFile,                  //文件句柄
            LPCVOID lpBuffer,                //数据缓存区指针
            DWORD nNumberOfBytesToWrite,       //你要写的字节数
            LPDWORD lpNumberOfBytesWritten,      //用于保存实际写入字节数的存储区域的指针
            LPOVERLAPPED lpOverlapped//OVERLAPPED  //结构体指针
          );

    返回值:

      成功返回非0的值

 

  1 #define UNICODE
  2 #include <tchar.h>
  3 #include <wchar.h>
  4 #include <windows.h>
  5 #include <exception>
  6 
  7 class WindowsException:public std::exception
  8 {
  9 public:
 10     WindowsException(DWORD dwErrorCode):m_dwErrorCode(dwErrorCode)
 11     {
 12     FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
 13                     nullptr,
 14                     m_dwErrorCode,
 15                     0,
 16                     reinterpret_cast<LPWSTR>(&m_strErrorMsg),
 17                     0,
 18                     nullptr);
 19     }
 20     ~WindowsException()
 21     {
 22         LocalFree(m_strErrorMsg);
 23     }
 24     const TCHAR* what() const
 25     {
 26         return  m_strErrorMsg;
 27     }
 28 private:
 29     DWORD m_dwErrorCode;
 30     TCHAR * m_strErrorMsg;
 31 };
 32 
 33 class MyFile
 34 {
 35 public:
 36         MyFile( const TCHAR *strFilePath ):m_hFile(INVALID_HANDLE_VALUE)                //构造函数
 37         {
 38             SetPath(strFilePath);
 39         }
 40         
 41         ~MyFile()                                        //析构函数
 42         {
 43             if( m_hFile != INVALID_HANDLE_VALUE)
 44             {
 45                 CloseHandle(m_hFile);
 46             }
 47         }
 48         BOOL OpenFileW( _In_ DWORD dwDesiredAccess = GENERIC_READ | GENERIC_WRITE,        //读写权限
 49                             _In_ DWORD dwShareMode = FILE_SHARE_READ,                        //共享读文件操作
 50                             _In_ DWORD dwCreationDisposition = OPEN_ALWAYS,                    //如文件不存在则创建它
 51                             _In_ DWORD dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL,            //默认属性
 52                             _In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes = NULL,            
 53                             _In_opt_ HANDLE hTemplateFile = NULL)
 54         {
 55             BOOL bRet = TRUE;
 56             m_hFile = CreateFileW( m_strFilePath,                                     //接收传递过来的参数
 57                                 dwDesiredAccess, 
 58                                 dwShareMode, 
 59                                 lpSecurityAttributes, 
 60                                 dwCreationDisposition, 
 61                                 dwFlagsAndAttributes, 
 62                                 hTemplateFile);
 63             if( m_hFile == INVALID_HANDLE_VALUE)                    //不等于说明打开成功  相等的话说明成功
 64             {
 65                 bRet = FALSE;
 66                 throw WindowsException(GetLastError());
 67             }
 68             return bRet;
 69         }
 70         VOID SetPath( const TCHAR *strFilePath)
 71         {
 72             SIZE_T nstrLen = _tcslen(strFilePath) + sizeof(TCHAR);
 73             m_strFilePath = new TCHAR(nstrLen);
 74             _tcscpy_s(m_strFilePath, nstrLen, strFilePath);
 75         }
 76         const TCHAR *GetPath() const
 77         {
 78             return m_strFilePath;
 79         }
 80 private:
 81     HANDLE m_hFile;
 82     TCHAR *m_strFilePath;
 83 
 84 };
 85 
 86 int main()
 87 {
 88     try
 89     {
 90         MyFile clsFile;
 91         clsFile.SetPath( TEXT("demo.txt"));
 92         clsFile.OpenFile();
 93     }
 94     catch(WindowsException &exception)
 95     {
 96         MessageBoxW(nullptr, exception.what(), exception.what(), MB_OK);
 97     }
 98 
 99 /*
100     HANDLE hFile = CreateFileW( L"Demo.txt",                            //文件名称
101                                  GENERIC_READ | GENERIC_WRITE,        //文件的访问权限
102                                  0,                                        //文件共享
103                                  nullptr,
104                                  OPEN_EXISTING,                        //文件必须已经存在。方式
105                                  FILE_ATTRIBUTE_NORMAL,                //默认属性
106                                  nullptr);                                //为空表示不使用模板,一般为空
107     if( hFile == INVALID_HANDLE_VALUE)    //如果存在的话弹出对话框
108                                             //INVALID_HANDLE_VALUE = -1 文件无法打开
109                                             //弹出对话框
110     {
111         MessageBox( nullptr, L"Error", L"Error", MB_OK );
112     }
113     
114     CloseHandle(hFile);                        //关闭句柄
115     
116 */
117     return 0;
118 }

 

以上是关于006 异步IO操作的主要内容,如果未能解决你的问题,请参考以下文章

如何用python实现异步io

Python异步IO

异步IO和协程

异步IO(协程,消息循环队列)

异步IO

异步IO