Win32 线程知识点梳理五

本章整理overlapped I/O 也就是异步I/O(asynchronous I/O)的内容。

overlapped I/O + completion ports 常被设计为多线程处理,可在I/O bound的程序中获得高效率。

众所周知:I/O设备是个慢速设备,让CPU干等I/O的完成不是一件明智的事情,因此一个解决方案就是,使用另一个线程来进行I/O,然而,这会产生一些相关的问题,就是如何在主线程中操控许多个worker线程、如何设定同步机制、如何处理错误情况、如何显示对话框等。

异步I/O是win32的一项技术,你可以要求操作系统为你传送数据,并且在传送完毕时通知你,操作系统内部正是以线程来完成异步I/O的。

Win32文件操作函数

win32 中有3个基本的函数用来执行I/O,它们是:

  • CreateFile()
  • ReadFile()
  • WriteFile()

没有专门的函数用来关闭文件,只要调用CloseHandle()即可。

CreateFile

用来打开各种资源包括文件,串行口和并行口,Named pipes,console

HANDLE WINAPI CreateFile(
  _In_     LPCTSTR               lpFileName,//文件名
  _In_     DWORD                 dwDesiredAccess, //存取模式,读或写
  _In_     DWORD                 dwShareMode,
  _In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes,
  _In_     DWORD                 dwCreationDisposition,
  _In_     DWORD                 dwFlagsAndAttributes,//文件属性
  _In_opt_ HANDLE                hTemplateFile
);

参数1:文件名称
参数2:存取模式:The most commonly used values are GENERIC_READ, GENERIC_WRITE, or both (GENERIC_READ | GENERIC_WRITE).
参数3:共享模式
详细见:https://msdn.microsoft.com/en-us/library/windows/desktop/aa363858(v=vs.85).aspx
参数4:指向安全属性结构
参数5:如何产生
参数6:文件属性,异步需要设置为FILE_FLAG_OVERLAPPED
参数7: 一个临时文件,将拥有全部的属性拷贝

一个不常被讨论的性质是,overlapped I/O可以在同一时间读文件的许多部分,这些操作都是用相同的文件handle,因此当你使用overlapped I/O时,没有所谓的目前的文件位置的这样的观念。

如果你发出多个overlapped请求
不能通过调用C runtime library 中的stdio.h函数来使用overlapped I/O。

ReadFile

BOOL WINAPI ReadFile(
  _In_        HANDLE       hFile,
  _Out_       LPVOID       lpBuffer,
  _In_        DWORD        nNumberOfBytesToRead,
  _Out_opt_   LPDWORD      lpNumberOfBytesRead,
  _Inout_opt_ LPOVERLAPPED lpOverlapped
);

参数1:将要读的文件
参数2:想要接收数据的缓冲区
参数3:欲读取的字节个数
参数4:实际读取的字节个数的地址
参数5:指针,指向overlapped info

这个函数很想c runtime函数中的fread(),差别在于最后一个参数lpOverlapped,如果CreateFile()第6个参数被指定为FILE_FLAG_OVERLAPPED,你就必须在上述的lpOverlapped参数中提供一个指针,指向一个OVERLAPPED结构。

WriteFile

BOOL WINAPI WriteFile(
  _In_        HANDLE       hFile,
  _In_        LPCVOID      lpBuffer,
  _In_        DWORD        nNumberOfBytesToWrite,
  _Out_opt_   LPDWORD      lpNumberOfBytesWritten,
  _Inout_opt_ LPOVERLAPPED lpOverlapped
);

参数1:将要写的文件
参数2:存储数据的缓冲区
参数3:欲写入的字节个数
参数4:实际写入的字节个数的地址
参数5:指针,指向overlapped info

OVERLAPPED结构

上文中提到的指针指向了一个OVERLAPPED结构,这个结构有什么用呢?
它主要起到两方面的作用:
1. 识别目前正在进行的overlapped操作
2. 在你和系统之间提供了一个共享区域,参数可以在该区域中双向传递。

typedef struct _OVERLAPPED {
  ULONG_PTR Internal;
  ULONG_PTR InternalHigh;
  union {
    struct {
      DWORD Offset;
      DWORD OffsetHigh;
    };
    PVOID  Pointer;
  };
  HANDLE    hEvent;
} OVERLAPPED, *LPOVERLAPPED;

参数1:通常被保留
参数2:通常被保留,当GetOverLappedResult()函数传回true时,这个栏目将内含被传输数据的长度
参数3:文件之中开始被读或被写的偏移位置,该偏移位置从文件头开始起算。如果目标设备没有支持文件位置,比如pipes,此栏位将被忽略
参数4:64位的文件偏移位置中,较高的32位,如果目标设备没有支持文件位置,比如pipes,此栏位将被忽略
参数5:一个manual-reset的event对象,当overlapped I/O完成时即被激发,ReadFileEx()和WriteFileEx()会忽略这个栏位,此时它可能被用来传递一个用户自定义的指针。

由于OVERLAPPED结构的生命期超越ReadFile()和WriteFile()函数,所以把这个结构放在一个安全的地方是很重要的事情,通常局部变量不是一个安全的地方,因为它会很快超过了生存范围,最安全的地方是heap。

被激发的File Handles

最简单的overlapped I/O类型是使用它自己的文件handle作为同步机制。
如果需要等待overlapped I/O执行结果,作为WaitForMultipleObjects()一部分,请在handles数组中加上这个文件handle,文件handle是一个核心对象,一旦操作完毕即被激发,当你完成操作之后,调用GetOverlappedResult() 确定结果如何。

GetOverLappedResult:

BOOL WINAPI GetOverlappedResult(
  _In_  HANDLE       hFile,
  _In_  LPOVERLAPPED lpOverlapped,
  _Out_ LPDWORD      lpNumberOfBytesTransferred,
  _In_  BOOL         bWait
);

参数1: 文件或设备的handle
参数2:一个指针,指向OVERLAPPED结构
参数3:一个指针,指向DWORD,用以表示真正被传输的字节个数
参数4:一个布尔值,用以表示是否要等待操作完成,TRUE表示要等待。
返回值:如果成功返回true,失败返回false。

下面这个程序的表示从文件C:\Windows\WINHLP32.EXE的第1500个位置读取512个字节

/*
 * IoByFile.c
 *
 * Sample code for Multithreading Applications in Win32
 * This is from Chapter 6, Listing 6-1
 *
 * Demonstrates how a file handle becomes signaled
 * when an overlapped operation on the handle's file
 * is completed.  Notice that sometimes the operation
 * is completed immediately. The operation is only
 * queued, or pended, if ERROR_IO_PENDING is returned.
 */

#define WIN32_LEAN_AND_MEAN
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>

//
// Constants
//
#define READ_SIZE       512

//
// Function prototypes
//
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值