您的位置:首页 > 其它

I/O Concepts(3) : 同步设备I/O 和 异步设备I/O

2010-12-05 19:36 357 查看
一、设备

各种常见设备表

设备

常见用途
打开方式
文件
永久存储任何数据
CreateFile(pszName为路径名或UNC路径名)
目录
属性和文件的压缩的设置
CreateFile(pszName为路径名或UNC路径名)。如果在调用CreateFile的时候指定FILE_FLAG_BACKUP_SEMANTICS标志,那么Windows允许我们打开一个目录。打开目录使我们能够改变目录的属性(比如正常、隐藏,等等)和它的时间戳
逻辑磁盘驱动器
格式化驱动器
CreateFile(pszName为”//./x:”)。其中x是磁盘驱动器盘符,打开驱动器使我们能够格式化驱动器或检测驱动器媒介的大小。
物理磁盘驱动器
访问分区表
CreateFile(pszName为 ”//./PHYSICALDRIVEx”),x是物理驱动器号。打开驱动器使我们能够直接访问硬盘的分区表。
串口
通过电话线传输数据
CreateFile(pszName为”COMx”)
并口
将数据传输至打印机
CreateFile(pszName为”LPTx”)
邮槽
一对多数据传输,通常是通过网络传到另一台运行Windows的机器上
邮槽服务器端:
CreateFile(pszName为”//./mailslot/mailslotname”)
邮槽客户端:

CreateFile(pszName为”//servername/mailslot/mailslotname”)
命名管道
一对一数据传输,通常是通过网络传到另一台运行Windows的机器上
命名管道服务器端:
CreateFile(pszName为”//./pipe/pipename”)
命名管道客户端:

CreateFile(pszName为”//servername/pipe/pipename”)
匿名管道
单机上的一对一数据传输(不跨网络)
CreatePipe用来打开服务器和客户端。
套接字
报文或数据流的传输,通常是通过网络传到任何支持套接字的机器上(机器不一定要运行Windows系统)
Socket, accept 或 AcceptEx
控制台
文本窗口的屏幕缓存
CreateConsolScreenBuffer 或 GetStdHandle
二、同步设备I/O 与 异步设备I/O

在CreateFile打开设备的时候,不指定FILE_FLAG_OVERLAPPED标志,则系统认为我们想要与设备进行同步I/O,相反就是异步I/O。

在同步设备I/O中,线程启动一次I/O操作并且立即进入等待状态,直到I/O操作完成。而对于异步I/O,线程通过调用某个函数将I/O请求发送到内核,如果内核接受了这次I/O操作,调用线程可以继续处理其他的任务直到内核通知该线程I/O操作已经完成。然后,线程可以转入对I/O操作的处理。

两种机制执行过程如下图所示:



三、对比示例:

同步I/O

#include <math.h>
#include <stdio.h>
#include <tchar.h>
#include <Windows.h>

double func()
{
DOUBLE fResult = 0;
for (double i = 0; i < 1000000; i = i + 1)
fResult += sin(tan(tan(i)));

return fResult;
}

const DWORD dwBufferSize = 10 * 1024 * 1024;	//缓冲大小
int _tmain(int argc, _TCHAR *argv[])
{
if (argc != 2)
{
printf("用法示例:Synchronous 文本文件名/n");
return 0;
}

HANDLE hFile;
LPVOID lpBuffer;

__try{
hFile = CreateFile(argv[1], GENERIC_READ, 0, NULL, OPEN_EXISTING
, FILE_FLAG_NO_BUFFERING | FILE_ATTRIBUTE_NORMAL
, NULL);	// 同步I/O, 没有FILE_FLAG_OVERLAPPED标志
if (hFile == INVALID_HANDLE_VALUE)
__leave;

lpBuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwBufferSize);
if (lpBuffer == NULL)
__leave;

DWORD dwBytesReaded, dwTime = GetTickCount();
// 同步I/O
BOOL bRet = ReadFile(hFile, lpBuffer, dwBufferSize, &dwBytesReaded, NULL);

func();		// 执行一些其他操作
printf("总共耗时: %d ms", GetTickCount() - dwTime);
}
__finally{
if (lpBuffer != NULL)
HeapFree(GetProcessHeap(), 0, lpBuffer);

if (hFile != INVALID_HANDLE_VALUE)
CloseHandle(hFile);
}
return 0;
}


异步I/O

#include <math.h>
#include <stdio.h>
#include <tchar.h>
#include <Windows.h>

double func()
{
DOUBLE fResult = 0;
for (double i = 0; i < 1000000; i = i + 1)
fResult += sin(tan(tan(i)));

return fResult;
}

const DWORD dwBufferSize = 10 * 1024 * 1024;	//缓冲大小
int _tmain(int argc, _TCHAR *argv[])
{
if (argc != 2)
{
printf("用法示例:Synchronous 文本文件名/n");
return 0;
}

HANDLE hFile;
LPVOID lpBuffer;
OVERLAPPED ovlp = { 0 };

__try{
hFile = CreateFile(argv[1], GENERIC_READ, 0, NULL, OPEN_EXISTING
, FILE_FLAG_NO_BUFFERING | FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED
, NULL);
if (hFile == INVALID_HANDLE_VALUE)
__leave;

lpBuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwBufferSize);
if (lpBuffer == NULL)
__leave;

DWORD dwTime = GetTickCount();
// 异步I/O
BOOL bRet = ReadFile(hFile, lpBuffer, dwBufferSize, NULL, &ovlp);

func();		// 执行一些其他操作

WaitForSingleObject(hFile, INFINITE);
printf("总共耗时: %d ms", GetTickCount() - dwTime);
}
__finally{
if (lpBuffer != NULL)
HeapFree(GetProcessHeap(), 0, lpBuffer);

if (hFile != INVALID_HANDLE_VALUE)
CloseHandle(hFile);
}
return 0;
}


在机器上实验,两者性能差异还是挺明显的,同步I/O要345ms完成,而异步I/O要235ms完成。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: