Github

https://github.com/gongluck/Windows-Core-Program.git

//第10章 同步设备IO与异步设备IO.cpp: 定义应用程序的入口点。
// #include "stdafx.h"
#include "第10章 同步设备IO与异步设备IO.h" //可提醒IO回调
VOID WINAPI funComplete(
_In_ DWORD dwErrorCode,
_In_ DWORD dwNumberOfBytesTransfered,
_Inout_ LPOVERLAPPED lpOverlapped
)
{ } //IO完成端口工作线程
DWORD WINAPI workthread(LPVOID lpThreadParameter)
{
DWORD NumberOfBytesTransferred;
DWORD CompletionKey;
OVERLAPPED* pOverlapped;
BOOL bres = GetQueuedCompletionStatus(lpThreadParameter, &NumberOfBytesTransferred, &CompletionKey, &pOverlapped, INFINITE);
//GetQueuedCompletionStatusEx可获取多个IO请求结果
DWORD dres = GetLastError(); return 0;
} int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPWSTR lpCmdLine,
_In_ int nCmdShow)
{
//打开(创建)文件
HANDLE hFile = CreateFile(TEXT("第10章 同步设备IO与异步设备IO.cpp"), GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ, nullptr, OPEN_EXISTING, 0, nullptr);
if (hFile == INVALID_HANDLE_VALUE)
{
MessageBox(nullptr, TEXT("打开文件失败!"), TEXT("error"), MB_OK);
return 0;
} //文件类型
DWORD dres = GetFileType(hFile);
//dres == FILE_TYPE_DISK //文件大小
LARGE_INTEGER li;
BOOL bres = GetFileSizeEx(hFile, &li);//逻辑大小
li.LowPart = GetCompressedFileSize(TEXT("第10章 同步设备IO与异步设备IO.cpp"), (DWORD*)&li.HighPart);//物理大小 //文件指针
li.QuadPart = 0;
bres = SetFilePointerEx(hFile, li, nullptr, FILE_END);
bres = SetFilePointerEx(hFile, li, &li, FILE_CURRENT);
bres = SetEndOfFile(hFile);
li.QuadPart = 0;
bres = SetFilePointerEx(hFile, li, nullptr, FILE_BEGIN); //同步IO
char* buf = new char[100];
bres = ReadFile(hFile, buf, 100, &dres, nullptr);
delete []buf;
buf = nullptr; //刷新缓冲区
bres = FlushFileBuffers(hFile); //CancelSynchronousIo
//取消线程未完成的同步IO请求 //关闭文件
CloseHandle(hFile);
hFile = nullptr; //异步IO
HANDLE hFile2 = CreateFile(TEXT("第10章 同步设备IO与异步设备IO.cpp"), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, nullptr);
OVERLAPPED ol;
ol.Offset = 1024;
ol.OffsetHigh = 0;
ol.hEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr);
char* buf2 = new char[1024];
bres = ReadFile(hFile2, buf2, 1024, nullptr, &ol);//异步方式总是返回FALSE
dres = GetLastError();
switch (dres)
{
case ERROR_IO_PENDING:
//IO请求添加成功
//WaitForSingleObject(hFile2, INFINITE);
WaitForSingleObject(ol.hEvent, INFINITE);
break;
case ERROR_INVALID_USER_BUFFER:
case ERROR_NOT_ENOUGH_MEMORY:
break;
case ERROR_NOT_ENOUGH_QUOTA:
break;
default:
break;
} //取消队列中的IO请求
//bres = CancelIo(hFile2);
bres = CancelIoEx(hFile2, &ol);
//bres = CancelIoEx(hFile2, nullptr);
//bres = CloseHandle(hFile2); if (ol.hEvent != nullptr)
{
CloseHandle(ol.hEvent);
ol.hEvent = nullptr;
} //可提醒IO
OVERLAPPED ol2;
ol2.Offset = 1024;
ol2.OffsetHigh = 0;
ol2.hEvent = nullptr;
dres = ReadFileEx(hFile2, buf2, 1024, &ol2, funComplete);//回调函数在同一个线程空间
//置为可提醒状态
//APC队列中只要有一个,线程就不会进入睡眠
dres = SleepEx(INFINITE, TRUE);
//WaitForSingleObjectEx
//WaitForMultipleObjectsEx
//SignalObjectAndWait
//GetQueuedCompletionStatusEx
//MsgWaitForMultipleObjectsEx
dres = GetLastError();//WAIT_IO_COMPLETION //手动添加一项到APC队列
//可以让目标线程结束睡眠
dres = QueueUserAPC((PAPCFUNC)funComplete, GetCurrentThread(), NULL); //IO完成端口
HANDLE iocp = CreateIoCompletionPort(hFile2, nullptr, 1, 2);
HANDLE hts[2];
for (int i = 0; i < 2; ++i)
hts[i] = CreateThread(nullptr, 0, workthread, iocp, 0, nullptr);
bres = PostQueuedCompletionStatus(iocp, 100, 1, &ol); //模拟发送IO请求完成
bres = ReadFile(hFile2, buf2, 1024, nullptr, &ol2);
dres = GetLastError(); WaitForMultipleObjects(2, hts, TRUE, INFINITE);
for (int i = 0; i < 2; ++i)
{
CloseHandle(hts[i]);
hts[i] = nullptr;
}
CloseHandle(iocp);
iocp = nullptr; CloseHandle(hFile2);
hFile2 = nullptr;
delete[]buf2;
buf2 = nullptr; system("pause");
return 0;
}

Windows核心编程:第10章 同步设备IO与异步设备IO的更多相关文章

  1. windows核心编程 第8章201页旋转锁的代码在新版Visual Studio运行问题

    // 全局变量,用于指示共享的资源是否在使用 BOOL g_fResourceInUse = FALSE; void Func1() { //等待访问资源 while(InterlockedExcha ...

  2. windows核心编程 第5章job lab示例程序 解决小技巧

    看到windows核心编程 第5章的最后一节,发现job lab例子程序不能在我的系统(win8下)正常运行,总是提示“进程在一个作业里”         用process explorer程序查看 ...

  3. windows核心编程---第七章 用户模式下的线程同步

    用户模式下的线程同步 系统中的线程必须访问系统资源,如堆.串口.文件.窗口以及其他资源.如果一个线程独占了对某个资源的访问,其他线程就无法完成工作.我们也必须限制线程在任何时刻都能访问任何资源.比如在 ...

  4. 《Windows核心编程》第九章——用内核对象进行线程同步

    先举一个有bug的例子: #include <iostream> #include <windows.h> #include <process.h> using n ...

  5. Windows核心编程 第十一章 线程池的使用

    第11章 线程池的使用 第8章讲述了如何使用让线程保持用户方式的机制来实现线程同步的方法.用户方式的同步机制的出色之处在于它的同步速度很快.如果关心线程的运行速度,那么应该了解一下用户方式的同步机制是 ...

  6. Windows核心编程 第七章 线程的调度、优先级和亲缘性(下)

    7.6 运用结构环境 现在应该懂得环境结构在线程调度中所起的重要作用了.环境结构使得系统能够记住线程的状态,这样,当下次线程拥有可以运行的C P U时,它就能够找到它上次中断运行的地方. 知道这样低层 ...

  7. Windows核心编程 第27章 硬件输入模型和局部输入状态

    第27章 硬件输入模型和局部输入状态 这章说的是按键和鼠标事件是如何进入系统并发送给适当的窗口过程的.微软设计输入模型的一个主要目标就是为了保证一个线程的动作不要对其他线程的动作产生不好的影响. 27 ...

  8. Windows核心编程 第十七章 -内存映射文件(下)

    17.3 使用内存映射文件 若要使用内存映射文件,必须执行下列操作步骤: 1) 创建或打开一个文件内核对象,该对象用于标识磁盘上你想用作内存映射文件的文件. 2) 创建一个文件映射内核对象,告诉系统该 ...

  9. Windows核心编程 第六章 线程基础知识 (上)

    第6章 线程的基础知识 理解线程是非常关键的,因为每个进程至少需要一个线程.本章将更加详细地介绍线程的知识.尤其是要讲述进程与线程之间存在多大的差别,它们各自具有什么作用.还要介绍系统如何使用线程内核 ...

  10. Windows核心编程 第三章 内核对象

    第3章内核对象 在介绍Windows API的时候,首先要讲述内核对象以及它们的句柄.本章将要介绍一些比较抽象的概念,在此并不讨论某个特定内核对象的特性,相反只是介绍适用于所有内核对象的特性. 首先介 ...

随机推荐

  1. Vue proxy

    npm run dev 我们访问的是localhost:8080 config文件夹下的index.js配置文件的dev dev: { env: require('./dev.env'), port: ...

  2. input 选择框改变背景小技巧

    最近在项目中遇到一个问题,想要改变input选择框的背景,然而,令我没有想到的是,竟然无法直接改变背景的颜色 通常情况下:我们都可以通过改变元素的 background-color 的值来改变元素的背 ...

  3. 生活实遇记-Kindle好久没用,屏幕一直处于电池状态,怎么解决?

    2018-01-02 实遇记-Kindle好久没用,屏幕一直处于电池状态,怎么解决? 今天我翻腾出自己的kindle,好久没用了,屏幕一直是一个电池状态,充电头+线充了2个钟头,按电源键木有反应,也是 ...

  4. Beta冲刺——第三天

    beta冲刺:第三天 各个成员今日完成的任务 成员 冯晓.马思远 彭辉.王爽 吴琼.郝延婷 今日完成任务 ·管理员管理功能模块下角色管理功能的完善测试 ·角色和权限部分代码规范 ·博客撰写 ·后台系统 ...

  5. ubuntu安装jdk,maven,tomcat

    ubuntu16.04安装jdk8 -jdk 检查是否安装成功 java -version 出现如上信息即安装成功 安装maven,先去官网下载指定版本的maven,个人使用apache-maven- ...

  6. 【VBA】杨辉三角

    Private Sub Workbook_Open() Dim loopA As Integer Dim loopB As Integer Dim loopNum As Integer Dim top ...

  7. SpringMCVC拦截器不拦截静态资源

    SpringMCVC拦截器不拦截静态资源 SpringMVC提供<mvc:resources>来设置静态资源,但是增加该设置如果采用通配符的方式增加拦截器的话仍然会被拦截器拦截,可采用如下 ...

  8. dtruss

    一.简介 系统调用跟踪工具.   二.实例

  9. Eigen使用矩阵作为函数参数

    1 使用矩阵作为函数参数介绍 文章来源Writing Functions Taking %Eigen Types as Parameters Eigen为了在函数中传递不同的类型使用了表达式模板技术. ...

  10. java【基础】正则表达式

    1 字符串判断 java的正则使用的是Pattern以及Matcher来配合使用的. 如果只是用来判断输入的字符串是否符合格式,推荐使用Matcher的matches方法. public static ...