zoukankan      html  css  js  c++  java
  • 《Windows via C/C++》学习笔记 —— 设备I/O之“同步的设备I/O”(系列文章)

      前面曾经讲过,设备I/O的方式有两种:同步和异步。本篇介绍一下同步设备I/O。主要涉及到两个函数:ReadFile和WriteFile。

      不要被这两个函数的名称迷惑,不仅可以将这两个作用于文件,也可以作用于其他设备:比如管道、邮槽等。

      最简单的设备I/O,可以通过ReadFile和WriteFile这两个函数来实现:

    复制代码
    BOOL ReadFile(
       HANDLE      hFile,         //设备对象句柄
       PVOID       pvBuffer,      //读取缓冲区
       DWORD       nNumBytesToRead,     //读取的字节数
       PDWORD      pdwNumBytes,         //返回实际读取的字节数
       OVERLAPPED* pOverlapped);        //重叠结构指针,仅在异步方式有用
    复制代码
    复制代码
    BOOL WriteFile(
       HANDLE      hFile,
       CONST VOID  *pvBuffer,
       DWORD       nNumBytesToWrite,
       PDWORD      pdwNumBytes,     //返回实际写入的字节数
       OVERLAPPED* pOverlapped);
    复制代码

      在同步方式下使用这2个函数进行设备I/O,在同步模式下,两个函数的最后一个参数pOverlapped都要设置为NULL。另外,必须要注意这一点:就是在用CreateFile创建或打开设备之时,其FLAG参数不能包括FLAG_FILE_OVERLAPPED,否则系统认为你想要异步地实现设备I/O。

      另外,ReadFile只能读取这些设备,即在使用CreateFile创建或打开设备的时候,该函数的FLAG参数中包括GENERIC_READ。而WriteFile只能写入这些设备,即使用CreateFile函数的时候,FLAG参数包括GENERIC_WRITE。

      邮槽、管道、文件、串行端口等设备是有自己的高速缓存的。如果在CreateFile函数的FLAG参数中没有包括FILE_FLAG_NO_BUFFERING,也就是可以将写入的数据暂存在缓冲区中,那么可以通过FlushFileBuffers来强行将暂存在与设备有关的缓冲区中的全部数据写入到设备中。

    BOOL FlushFileBuffers(HANDLE hFile);

      同步方式的设备I/O实现简单,但是缺点也是明显的,就是会阻碍有关线程中的其他与设备I/O无关的操作。因为设备I/O函数直到设备I/O请求结束才返回,如果数据量大,很可能会阻碍其他无关的操作。

      为了解决这个问题,你应该尽量使用异步的设备I/O。但是可惜的是,Windows API中,没有为CreaetFile这个函数提供任何异步的方式来实现。Windows Vista提供了另一种方法:中途取消同步设备I/O。可以通过使用函数CancelSynchronousIo来取消一个线程之内的正在进行的同步设备I/O操作。

    BOOL CancelSynchronousIo(HANDLE hThread);     //参数是线程句柄

      该函数接受一个线程句柄,该句柄是一个正在等待同步设备I/O操作完成的线程的句柄。该句柄在创建或打开的时候,必须具有THREAD_TERMINATE操作权限。如果你调用CreateThread或_beginthreadex函数来创建线程,那么返回的线程句柄就包含THREAD_TERMINATED的操作权限。如果使用OpenThread函数来获得一个已创建的线程的句柄,那么就传递THREAD_TERMINATED给dwDesiredAccess参数(第1个参数)。如果没有设置该权限,那么CancelSynchronousIo返回FALSE,调用GetLastError返回ERROR_ACCESS_DENIED(访问拒绝错误)。

      如果线程已经结束了等待设备I/O,那么再调用CancelSynchronousIo函数会返回TRUE,而不是FLASE,调用GetLastError则返回ERROR_OPERATION_ABORTED(操作失败错误)。

      如果线程并不是等待在设备I/O的返回上,那么调用该函数会返回FALSE,随后调用GetLastError会返回ERROR_NO_FOUND(未找到的错误)。

    http://www.cnblogs.com/wz19860913/archive/2008/08/18/1270523.html

  • 相关阅读:
    Math 和 Date
    GRID布局
    移动端项目布局类型
    媒体查询 + rem用法
    字符串
    ES5 中常见的数组常用方法
    数组的排序
    毕设制作:前端界面 2020-02-01
    阅读笔记十六——排序算法
    阅读笔记十五——阿里面试题
  • 原文地址:https://www.cnblogs.com/findumars/p/6372335.html
Copyright © 2011-2022 走看看