在CreateFile的时候, 通过指定FILE_FLAG_NO_BUFFERING标志, 我们告诉告诉操作系统缓冲管理器, 我们不希望它对任何数据进行缓存, 而是将数据直接和我们自己的缓冲区交换, 这个标志可以提高应用程序的性能和内存的使用.
由于文件系统的设备驱动程序会将文件数据直接写入到我们提供的缓存中, 因此我们必须遵循一定的规则:
1、在访问文件的时候,使用的偏移量必须正好是磁盘扇区大小的整数倍(可以通过GetDiskFreeSpace函数来确定磁盘扇区的大小,一般是512B)
2、读取/写入的文件字节数必须正好是扇区大小的整数倍。
3、必须确保我们自己的缓冲区在进程地址空间中的起始地址正好是扇区大小的整数倍。(一种方法是通过VirtualAlloc函数来分配内存,VirtualAlloc分配的内存是页对齐的,内存页面大小一般是4096B,从而保证了是扇区大小的整数倍)
随便写的一份代码,但还是花了很长时间~~,主要是对高性能I/O没什么太大的映像吧~~
代码是读取一份文档,并在控制台中显示出来,很大的都行吧~
#define ROUND_UP_SIZE(Value,Pow2) /
((SIZE_T) ((((ULONG)(Value)) + (Pow2) - 1) /
& (~(((LONG)(Pow2)) - 1))))
#define ROUND_UP_PTR(Ptr,Pow2) /
((void *) ((((ULONG_PTR)(Ptr)) + (Pow2) - 1) /
& (~(((LONG_PTR)(Pow2)) - 1))))
int _tmain(int argc, _TCHAR *argv[])
{
DWORD dwBytesTransfer = 2000;
DWORD dwSectorSize;
HANDLE hFile;
LPVOID lpBuffer;
OVERLAPPED ovlp = { 0 };
if (argc != 2)
{
_tprintf(_T("命令格式:/tshowfile 文件名/n"));
return 1;
}
//获得dwSectorSize,一般是512
GetDiskFreeSpace(NULL, NULL, &dwSectorSize, NULL, NULL);
// 对每次传输字节数进行向上取整到dwSectorSize的倍数
dwBytesTransfer = ROUND_UP_SIZE(dwBytesTransfer, dwSectorSize);
__try{
DWORD dwSizeNeeded = dwSectorSize + dwBytesTransfer; //缓冲区多预留一个扇区大小
// 堆分配,然后内存对齐
lpBuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwSizeNeeded);
lpBuffer = ROUND_UP_PTR(lpBuffer, dwSectorSize); // 对齐内存
// 这种方法不需要内存对齐,VirtualAlloc分配出来的是页面对齐的。
//lpBuffer = VirtualAlloc(NULL, dwSizeNeeded, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
//if (lpBuffer == NULL)
// __leave;
//ZeroMemory(lpBuffer, dwSizeNeeded);
hFile = CreateFile(argv[1], GENERIC_READ, 0
,NULL, OPEN_EXISTING
,FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED | FILE_FLAG_NO_BUFFERING
,NULL);
if (hFile == INVALID_HANDLE_VALUE)
__leave;
BOOL bResult, bContinue = TRUE;
BOOL dwError;
do{
bResult = ReadFile(hFile, lpBuffer, dwBytesTransfer, NULL, &ovlp);
if (!bResult)
{
switch(dwError = GetLastError())
{
case ERROR_HANDLE_EOF:
bContinue = FALSE;
break;
case ERROR_IO_PENDING:
WaitForSingleObject(hFile, INFINITE);
printf("%s", lpBuffer); // txt文件默认保存的是ANSI格式,所以用printf
ovlp.Offset += dwBytesTransfer;
break;
}
}
}while ( bContinue );
}
__finally {
if (hFile != INVALID_HANDLE_VALUE)
CloseHandle(hFile);
if (lpBuffer != NULL)
VirtualFree(lpBuffer, 0, MEM_RELEASE);
}
return 0;
}