異步IO
使用異步IO的四種提醒方式
1.使用裝置核心對象進行提醒進行異步檔案操作的提醒2.使用事件核心對象提醒提醒同步以及互動,是一種完全不同的的提醒3.可提醒IO不可跨線程的4.I/O完成端口使用最廣泛
使用事件核心對象提醒
示例
#include<windows.h>
int main()
{
HANDLE hFile =CreateFile(TEXT("demo.txt",GENERIC_READ|GENERAIC_WRITE,FILE_SHARE,nullptr,OPEN_ALWAYS,FILE_FALG_OVERLAPPED,NULL);
if(hFile != INVALID_HANDLE_VALUE)
{
//read
BYTE bReadBuffer[]={};
OVERLAPPED oRead ={};
oRead.Offset=;
oRead.hEvent = CreateEvent(nullptr,TRUE,FALSE,TEXT("ReadEvent"));//事件核心對象,是獨立于程式之外的,屬于作業系統的,通過name在各個程式中使用
ReadFile(hFile,bReadBuffer,sizeof(bReadBuffer),nullptr,&oRead);
//write
BYTE bWriteBuffer[]={};
OVERLAPPED oWrite ={};
oWrite.Offset=;
oWrite.hEvent = CreateEvent(nullptr,TRUE,FALSE,TEXT("WriteEvent"));//事件核心對象,是獨立于程式之外的,屬于作業系統的,通過name在各個程式中使用
WriteFile(hFile,bWriteBuffer,sizeof(bWriteBuffer),nullptr,&oWrite);
//做其它的事情...異步最好的地方,就在于不會發生阻塞
//其它線程
HANDLE hOverLapped[]={};
hOverLapped[]=oRead.hEvent;
hOverLapped[]=oWrite.hEvent;
while (TRUE)
{
DWORD dwCase = WaitForMultipleObjects(, hOverLapped, FALSE, INFINITE);//進行事件對象的提醒
switch (dwCase - WAIT_OBJECT_0)
{
case :
// 讀完成
break;
case :
// 寫完成
break;
}
}
}
else
{
//GetLastError
}
}
程式領空與系統領空系統領空是所有程式共用的,事件核心對象存在于系統領空,那麼程式與程式之間的互動就可以通過事件核心對象,也可以通過事件核心對象中的對象來判斷狀态
可提醒IO
事件核心對象提醒:可提醒IO:發送請求
做自己的事情
判斷請求是否完成
發送請求
完成後,作業系統提醒我
APC機制
程序是工廠,線程是勞工,線上程的内部,它有一個機制:APC
當勞工閑的時候(前提),來做APC清單中的事情當線程空閑的時候(線程為可提醒狀态下),自動執行APC清單中的事情比如:MessageBox會導緻線程阻塞,當這個線程阻塞的時候,看上去線程閑下來了,但是并不是可提醒狀态,在windows中,隻有Wait函數、Sleep函數才能真正的“閑”下來相當于一個不定時的定時器,APC不确定啥時候會被觸發,但是隻要觸發就會去做事情
提醒IO就是依托于APC來做的
示例
#include<windows.h>
int main()
{
HANDLE hFile =CreateFile(TEXT("demo.txt",GENERIC_READ|GENERAIC_WRITE,FILE_SHARE,nullptr,OPEN_ALWAYS,FILE_FLAG_OVERLAPPED,NULL));
if(hFile != INVALID_HANDLE_VALUE)
{
CONST UINT unLen = ;
// Read
OVERLAPPED oRead = {};//此時裡面的東西都不用設定,Offset可以設定,但是Event不能設定
oRead.Offset = ;
BYTE bReadBuf[unLen] = {};
// 異步讀取檔案 通過可提醒IO
ReadFileEx(hFile, bReadBuf, unLen, &oRead,FileIOCommpletionRoutineRead);
// 可以使得線程為可提醒狀态的函數
// SleepEx
// Wait.... 函數
SleepEx(, TRUE);//BOOL值代表,當SleepEx被調用的時候,是否把自己設定為空閑狀态,不設定為TRUE的時候,也就相當于阻塞但非可提醒狀态,此時APC不會被調用,是以這個BOOL值很重要
}
else
{
//GetLastError
}
}
可提醒不是那麼好用:回調函數參數太少,作用有限,可通過全局來傳入參數,但是邏輯會混亂
完成端口機制
操作異步IO最為友善、科學的方式以上三種都是一個線程之内來做的事情,可提醒IO可以讓别的線程來做這件事情,但是做起來較為麻煩,使用的是串行模型來進行異步IO操作異步IO操作最适合的是并行模式,是多線程。
windows是多程序的
多程序但是在單核時代,是模拟出來的多程序,隻是CPU運作速度快,我們沒感覺而已
多核下,每個核都可以運作一個線程(無切換), 也可以進行線程切換
如果程序隻有一個線程,那麼一個程式隻能做一件事情,如果需要做兩件事情,那麼就需要兩個程序,但是,兩個程序都會有一個核心對象,如果兩個程序進行互動的話,那麼會耗費大量的資源,是以在程序之下設計了線程多線程線程之間的切換也會耗費資源,隻是比線程之間切換要好點。核心數增加之後,并行模式開始流行起來完成端口是天生的并行模式,使用它來異步操作大檔案的時候會更快