從網(wǎng)上整理的文章,同樣,這只是為了我增加理解記憶而做到得筆記,
不存在利用價(jià)值,純粹是學(xué)習(xí)和記憶.抄襲也好學(xué)習(xí)也好只是讓人明
白道理.主要干活的還是自己的程序.
I/O設(shè)備處理必然讓主程序停下來(lái)干等I/O的完成,
對(duì)這個(gè)問(wèn)題有
方法一:使用另一個(gè)線(xiàn)程進(jìn)行I/O。這個(gè)方案可行,但是麻煩。
方法二:使用overlapped I/O。
正如書(shū)上所說(shuō):“overlapped
I/O是WIN32的一項(xiàng)技術(shù),
你可以要求操作系統(tǒng)為你傳送數(shù)據(jù),并且在傳送完畢時(shí)通知你。
這項(xiàng)技術(shù)使你的程序在I/O進(jìn)行過(guò)程中仍然能夠繼續(xù)處理事務(wù)。
事實(shí)上,操作系統(tǒng)內(nèi)部正是以線(xiàn)程來(lái)I/O完成overlapped I/O。
你可以獲得線(xiàn)程的所有利益,而不需付出什么痛苦的代價(jià)”。
怎樣使用overlapped I/O:
進(jìn)行I/O操作時(shí),指定overlapped方式
使用CreateFile
(),將其第6個(gè)參數(shù)指定為FILE_FLAG_OVERLAPPED,
就是準(zhǔn)備使用overlapped的方式構(gòu)造或打開(kāi)文件;
如果采用
overlapped,那么ReadFile()、WriteFile()的第5個(gè)參數(shù)必須提供一個(gè)指針,
指向一個(gè)OVERLAPPED結(jié)構(gòu)。
OVERLAPPED用于記錄了當(dāng)前正在操作的文件一些相關(guān)信息。
//功能:從指定文件的1500位置讀入300個(gè)字節(jié)
int main()
{
BOOL
rc;
HANDLE hFile;
DWORD
numread;
OVERLAPPED overlap;
char
buf[512];
char
szPath=”x:\\xxxx\xxxx”;
//檢查系統(tǒng),確定是否支持overlapped,(NT以上操作系統(tǒng)支持OVERLAPPED)
CheckOsVersion();
//
以overlapped的方式打開(kāi)文件
hFile = CreateFile(
szPath,
GENERIC_READ,
FILE_SHARE_READ|FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_FLAG_OVERLAPPED,
NULL
);
// OVERLAPPED結(jié)構(gòu)實(shí)始化為0
memset(&overlap, 0, sizeof(overlap));
//指定文件位置是1500;
overlap.Offset =
1500;
rc =
ReadFile(hFile,buf,300,&numread,&overlap);
//因?yàn)槭莖verlapped操作,ReadFile會(huì)將讀文件請(qǐng)求放入讀隊(duì)列之后立即返回(false),
//而不會(huì)等到文件讀完才返回(true)
if (rc)
{
//文件真是被讀完了,rc為true
//
或當(dāng)數(shù)據(jù)被放入cache中,或操作系統(tǒng)認(rèn)為它可以很快速地取得數(shù)據(jù),rc為true
}
else
{
if (GetLastError() ==
ERROR_IO_PENDING)
{//當(dāng)錯(cuò)誤是ERROR_IO_PENDING,那意味著讀文件的操作還在進(jìn)行中
//等候,直到文件讀完
WaitForSingleObject(hFile,
INFINITE);
rc =
GetOverlappedResult(hFile,&overlap,&numread,FALSE);
//上面二條語(yǔ)句完成的功能與下面一條語(yǔ)句的功能等價(jià):
//
GetOverlappedResult(hFile,&overlap,&numread,TRUE);
}
else
{
//出錯(cuò)了
}
}
CloseHandle(hFile);
return
EXIT_SUCCESS;
}
在實(shí)際工作中,若有幾個(gè)操作同一個(gè)文件時(shí),
怎么辦?我們可以利用OVERLAPPED結(jié)構(gòu)中提供的event來(lái)解決上面遇到的問(wèn)題。
注意,你所使用的event對(duì)象必須是一個(gè)MANUAL型的;否則,可能產(chǎn)生競(jìng)爭(zhēng)條件。
原因見(jiàn)書(shū)P159。
int
main()
{
int i;
BOOL
rc;
char szPath=”x:\\xxxx\xxxx”;
//
以overlapped的方式打開(kāi)文件
ghFile = CreateFile(
szPath,
GENERIC_READ,
FILE_SHARE_READ|FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_FLAG_OVERLAPPED,
NULL
);
for (i=0; i<MAX_REQUESTS; i++)
{
//將同一文件按幾個(gè)部分按overlapped方式同時(shí)讀
//注意看QueueRequest函數(shù)是如何運(yùn)做的,每次讀16384個(gè)塊
QueueRequest(i, i*16384, READ_SIZE);
}
// 等候所有操作結(jié)束;
//隱含條件:當(dāng)一個(gè)操作完成時(shí),其對(duì)應(yīng)的event對(duì)象會(huì)被激活
WaitForMultipleObjects(MAX_REQUESTS, ghEvents, TRUE,
INFINITE);
// 收尾操作
for (i=0;
i<MAX_REQUESTS; i++)
{
DWORD
dwNumread;
rc =
GetOverlappedResult(
ghFile,
&gOverlapped[i],
&dwNumread,
FALSE
);
CloseHandle(gOverlapped[i].hEvent);
}
CloseHandle(ghFile);
return
EXIT_SUCCESS;
}
//當(dāng)讀操作完成以后,gOverlapped[nIndex].hEvent會(huì)系統(tǒng)被激發(fā)
int QueueRequest(int nIndex,
DWORD dwLocation, DWORD dwAmount)
{
//構(gòu)造一個(gè)MANUAL型的event對(duì)象
ghEvents[nIndex] = CreateEvent(NULL,
TRUE, FALSE, NULL);
//將此event對(duì)象置入OVERLAPPED結(jié)構(gòu)
gOverlapped[nIndex].hEvent =
ghEvents[nIndex];
gOverlapped[nIndex].Offset =
dwLocation;
for (i=0; i<MAX_TRY_COUNT;
i++)
{
//文件ghFile唯一
rc = ReadFile(ghFile,
gBuffers[nIndex],&dwNumread,&gOverlapped[nIndex]);
if (rc)
return
TRUE;
err =
GetLastError();
if (err ==
ERROR_IO_PENDING)
{
//當(dāng)錯(cuò)誤是ERROR_IO_PENDING,那意味著讀文件的操作還在進(jìn)行中
return TRUE;
}
//
處理一些可恢復(fù)的錯(cuò)誤
if ( err ==
ERROR_INVALID_USER_BUFFER
||
err ==
ERROR_NOT_ENOUGH_QUOTA
||
err ==
ERROR_NOT_ENOUGH_MEMORY )
{
sleep(50);
continue;//重試
}
//
如果GetLastError()返回的不是以上列出的錯(cuò)誤,放棄
break;
}
return -1;
}