[笔记]Windows核心编程《九》同步设备I/O和异步设备I/O

简介: Windows核心编程《九》同步设备I/O和异步设备I/O

系列文章目录



[笔记]Windows核心编程《一》错误处理、字符编码

[笔记]Windows核心编程《二》内核对象

[笔记]Windows核心编程《三》进程

[笔记]Windows核心编程《四》作业

[笔记]快乐的LInux命令行《五》什么是shell

[笔记]Windows核心编程《五》线程基础

[笔记]Windows核心编程《六》线程调度、优先级和关联性

[笔记]Windows核心编程《七》用户模式下的线程同步

[笔记]Windows核心编程《八》用内核对象进行线程同步

[笔记]Windows核心编程《九》同步设备I/O和异步设备I/O

[笔记]Windows核心编程《十一》Windows线程池

[笔记]Windows核心编程《十二》纤程

[笔记]Windows核心编程《十三》windows内存体系结构

[笔记]Windows核心编程《十四》探索虚拟内存

[笔记]Windows核心编程《十五》在应用程序中使用虚拟内存

[笔记]Windows核心编程《十六》线程栈

[笔记]Windows核心编程《十七》内存映射文件

[笔记]Windows核心编程《十八》堆栈

[笔记]Windows核心编程《十九》DLL基础

[笔记]Windows核心编程《二十》DLL的高级操作技术

[笔记]Windows核心编程《二十一》线程本地存储器TLS

[笔记]Windows核心编程《二十二》注入DLL和拦截API

[笔记]Windows核心编程《二十三》结构化异常处理


文章目录



   系列文章目录

   打开和关闭设备

       细看CreateFile函数

   使用文件设备

       取得文件的大小

       设置文件指针的位置

   执行同步设备I/O

   异步设备I/O基础

   接受I/O请求完成通知

       触发设备内核对象

       可提醒I/O

       I/O完成端口

   篇外


打开和关闭设备


设备:定义为能与之通信的任何东西。

表1:各种设备及其常见用途

图片.png

Windows允许我们以相同的方式来从设备读取数据和向设备写入数据,而不必关心他是何种类型的设备。

当然各种设备之间还是存在差异。

例如对于串口来说,设置波特率是合理的,但在使用命名管道来进行跨网络传输,波特率就没有意义。

文件是最常用的设备之一。

表2:用来打开各种设备的函数

图片.png


细看CreateFile函数

HANDLE CreateFileW(
  LPCWSTR               lpFileName,
  DWORD                 dwDesiredAccess,
  DWORD                 dwShareMode,
  LPSECURITY_ATTRIBUTES lpSecurityAttributes,
  DWORD                 dwCreationDisposition,
  DWORD                 dwFlagsAndAttributes,
  HANDLE                hTemplateFile
);


大多数以句柄为返回值的Windows函数在失败的时候会返回NULL。但是,CreateFile返回INVALID_HANDLE_VALUE


使用文件设备


取得文件的大小

WINBASEAPI
BOOL
WINAPI
GetFileSizeEx(
    _In_ HANDLE hFile,
    _Out_ PLARGE_INTEGER lpFileSize
    );


hFile 一个已经打开的文件句柄;

lpFileSize是一个LARGE_INTEGER联合类型的地址。


设置文件指针的位置

文件内核对象有一个文件指针64位偏移量,表明应该在哪里执行下一次同步读取或写入操作。初始值为0

例如一下代码先读取前10个字节到缓存,然后再把后10个字节读取到缓存中。


执行同步设备I/O


同步设备IO, 可以是文件,邮件槽,管道,套接字等。

最常见的操作就是读写数据。

WINBASEAPI
_Must_inspect_result_
BOOL
WINAPI
ReadFile(
    _In_ HANDLE hFile,
    _Out_writes_bytes_to_opt_(nNumberOfBytesToRead, *lpNumberOfBytesRead) __out_data_source(FILE) LPVOID lpBuffer,
    _In_ DWORD nNumberOfBytesToRead,
    _Out_opt_ LPDWORD lpNumberOfBytesRead,
    _Inout_opt_ LPOVERLAPPED lpOverlapped
    );
WINBASEAPI
BOOL
WINAPI
WriteFile(
    _In_ HANDLE hFile,
    _In_reads_bytes_opt_(nNumberOfBytesToWrite) LPCVOID lpBuffer,
    _In_ DWORD nNumberOfBytesToWrite,
    _Out_opt_ LPDWORD lpNumberOfBytesWritten,
    _Inout_opt_ LPOVERLAPPED lpOverlapped
    );


hFile:表示要访问的设备句柄。 (打开设备时不要执行FILE_FLAG_OVERLAPPED标志,否则系统会认为我们想要与设备执行异步IO)

lpBuffer:执行一个缓存,函数会把数据读取到该缓存中,或者把缓存中的数据写入设备。

nNumberOfBytesToRead:(要读取的字节)

nNumberOfBytesToWrite :(要写入多少字节)

lpNumberOfBytesRead:(返回实际读取的字节)

lpNumberOfBytesWritten:(返回实际写入的字节)

lpOverlapped:(设置为NULL 表示执行同步读写)

ReadFile:(用于使用GENERIC_READ打开的设备)

WriteFile:(用于使用GENERIC_WRITE打开的设备)


异步设备I/O基础


和计算机执行的其他操作相比,设备IO是其中最慢,最不可预测的操作之一。

异步IO就是,将IO请求加入请求队列,由设备的驱动程序来执行IO,应用程序当前的线程不会被挂起。

CreateFile dwFlagsAndAttributes参数中指定FILE_FLAG_OVERLAPPED标志来打开设备。


接受I/O请求完成通知


windows提供了4种不同方法来接收IO请求已经完成的通知。

图片.png


触发设备内核对象

ReadFile和WriteFile函数将IO请求添加到队列之前,会先将设备内核对象设置为未触发状态。当设备驱动完成了请求以后,驱动程序会将设备内核对象设置为非触发状态。


一旦一个线程触发了一个异步I/O请求,该线程将会继续运行,以执行其它有用的任务。但即便如此,线程最终海华丝需要与I/O操作的完成状态进行同步。我 们会继续运行到线程代码中的一个点,在这个点上,除非设备数据已经被载入到缓存中,否则线程将无法执行后继操作。在Windows中设备内核对象可以用来 进行线程同步,因此对象既可能处于触发状态,也可能处于未触发状态。ReadFile和WriteFile函数在将I/O请求添加到队列之前,会先将设备 内核对象设为未触发状态,当设备驱动程序完成了请求之后,驱动程序会将设备内核对象设为触发状态。


可提醒I/O

当系统创建一个线程的时候,会同时创建一个与线程相关联的队列。这个队列被称为异步过程调用(asynchronous procedure call,APC)队列。当发出一个I/O请求的时候,我们可以告诉设备驱动程序在调用线程的APC队列中添加一项。


I/O完成端口

I/O 完成端口背后的理论是并发运行的线程的数量必须有一个上限——也就是说,同时发出的500个客户请求不应该允许出现500个可运行的线程。如果能在应用程 序初始化的时候创建一个线程池,并让线程池中的线程在应用程序运行期间一直保持可用状态,那么服务应用程序的性能就能得到提高。I/O完成端口的设计初衷 就是与线程池配合使用。


篇外


用HOOK来修改API函数的功能(5)-EXE和WDM驱动通信

通常EXE和WDM驱动通信有2种方法:

1:使用DeviceIOControl函数。

2:使用自定义事件。


相关:

参考1

参考2

参考3

参考4

Windows核心编程-CreateFile详解

基于visual c++之windows核心编程代码分析(6)分配和释放可读可写的虚拟内存页面

基于visual c++之windows核心编程代码分析(24)IO控制、内核通信

基于visual c++之windows核心编程代码分析(25)检测U盘控制开关机

【CreateFileA】创建或打开文件或I / O设备

微软 调用 DeviceIoControl Demo

DeviceIoControl 函数详细解析



相关文章
|
3月前
|
监控 Ubuntu Linux
视频监控笔记(五):Ubuntu和windows时区同步问题-your clock is behind
这篇文章介绍了如何在Ubuntu和Windows系统中通过设置相同的时区并使用ntp服务来解决时间同步问题。
90 4
视频监控笔记(五):Ubuntu和windows时区同步问题-your clock is behind
|
4月前
|
网络协议 API Windows
MASM32编程调用 API函数RtlIpv6AddressToString,windows 10 容易,Windows 7 折腾
MASM32编程调用 API函数RtlIpv6AddressToString,windows 10 容易,Windows 7 折腾
|
4月前
|
Windows
[原创]用MASM32编程获取windows类型
[原创]用MASM32编程获取windows类型
|
4月前
|
JavaScript 前端开发 API
MASM32编程通过WMI获取Windows计划任务
MASM32编程通过WMI获取Windows计划任务
|
4月前
|
API Windows
MASM32编程获取Windows当前桌面主题名
MASM32编程获取Windows当前桌面主题名
|
5月前
|
编译器 开发工具 C语言
解锁QtCreator跨界神技!Windows下轻松驾驭OpenCV动态库,让你的跨平台开发如虎添翼,秒变视觉编程大师!
【8月更文挑战第4天】QtCreator是一款强大的跨平台IDE,便于创建多平台应用。本教程教你如何在Windows环境下集成OpenCV库至Qt项目。首先,下载匹配MinGW的OpenCV预编译版并解压。接着,在QtCreator中新建或打开项目,并在.pro文件中添加OpenCV的头文件和库文件路径。确保编译器设置正确。随后编写测试代码,例如加载和显示图片,并进行编译运行。完成这些步骤后,你就能在QtCreator中利用OpenCV进行图像处理开发了。
272 6
|
6月前
|
Linux Apache C++
FFmpeg开发笔记(三十五)Windows环境给FFmpeg集成libsrt
该文介绍了如何在Windows环境下为FFmpeg集成SRT协议支持库libsrt。首先,需要安装Perl和Nasm,然后编译OpenSSL。接着,下载libsrt源码并使用CMake配置,生成VS工程并编译生成srt.dll和srt.lib。最后,将编译出的库文件和头文件按照特定目录结构放置,并更新环境变量,重新配置启用libsrt的FFmpeg并进行编译安装。该过程有助于优化直播推流的性能,减少卡顿问题。
151 2
FFmpeg开发笔记(三十五)Windows环境给FFmpeg集成libsrt
|
5月前
|
数据库 Windows
超详细步骤解析:从零开始,手把手教你使用 Visual Studio 打造你的第一个 Windows Forms 应用程序,菜鸟也能轻松上手的编程入门指南来了!
【8月更文挑战第31天】创建你的第一个Windows Forms (WinForms) 应用程序是一个激动人心的过程,尤其适合编程新手。本指南将带你逐步完成一个简单WinForms 应用的开发。首先,在Visual Studio 中创建一个“Windows Forms App (.NET)”项目,命名为“我的第一个WinForms 应用”。接着,在空白窗体中添加一个按钮和一个标签控件,并设置按钮文本为“点击我”。然后,为按钮添加点击事件处理程序`button1_Click`,实现点击按钮后更新标签文本为“你好,你刚刚点击了按钮!”。
380 0
|
6月前
|
存储 安全 数据安全/隐私保护
Windows 32 汇编笔记(一):基础知识
Windows 32 汇编笔记(一):基础知识
|
5月前
|
存储 编译器 Linux
Windows 32 汇编笔记(二):使用 MASM
Windows 32 汇编笔记(二):使用 MASM