久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

《Windows核心編程系列》九談?wù)勍皆O(shè)備IO與異步設(shè)備IO之同步設(shè)備IO

 求真我 2014-04-20

http://blog.csdn.net/ithzhang/article/details/8307633


同步設(shè)備IO

所謂同步IO是指線程在發(fā)起IO請(qǐng)求后會(huì)被掛起,,IO完成后繼續(xù)執(zhí)行。

 

異步IO是指:線程發(fā)起IO請(qǐng)求后并不會(huì)掛起而是繼續(xù)執(zhí)行,。IO完畢后會(huì)得到設(shè)備的通知,。而IO完成端口就是實(shí)現(xiàn)這種通知的很好的一種方式。

 

線程是我們開發(fā)高性能,、響應(yīng)性好的一個(gè)必不可少的工具,。這樣在多處理器上就可以同時(shí)執(zhí)行多個(gè)操作,,從而提高吞吐量,。當(dāng)線程發(fā)出一個(gè)同步設(shè)備IO請(qǐng)求的時(shí)候,它會(huì)被臨時(shí)掛起,,直到設(shè)備完成IO請(qǐng)求為止,。但線程阻塞會(huì)損害性能,,這里有個(gè)問題是我們?nèi)绾巫尵€程不被掛起。

 

讓線程始終進(jìn)行有用的工作就需要它們相互通信,,鼎力配合,。Windows經(jīng)過數(shù)年的研究和測(cè)試,開發(fā)出了一種被稱為IO完成端口的機(jī)制的技術(shù),。它可以幫助我們創(chuàng)建高性能而且伸縮性好的應(yīng)用程序,。通過使用完成端口我們可以讓線程在讀取設(shè)備和寫入設(shè)備而不必等待設(shè)備的響應(yīng),從而顯著的提高吞吐量,。

 

    作為Windows程序員都必須要完全理解IO完成端口的工作原理,。

 

    Windows支持多種不同種類的設(shè)備。在此,,我們把設(shè)備定義為能夠與之進(jìn)行通信的任何東西,。如文件、目錄,、串口,、并口、套接字,、控制臺(tái)等,。接下來討論是與這些設(shè)備進(jìn)行通信,此種方式下與線程通信時(shí),,線程需要掛起等待設(shè)備響應(yīng)---這種方式被稱為同步IO,。

 

    Windows向開發(fā)人員隱藏了各種設(shè)備的差異,許多WindowsAPI允許我們以相同的方式來從設(shè)備讀取數(shù)據(jù)和向設(shè)備寫入數(shù)據(jù),,而不必關(guān)心何種類型的設(shè)備,。

 

CreateFile函數(shù)。

 

    CreateFile當(dāng)然可以創(chuàng)建和打開磁盤文件,。但是不要被它的名字所迷惑,。它同樣可以打開其他設(shè)備。根據(jù)傳入?yún)?shù)的不同可以讓CreateFile打開不同的設(shè)備,。

 

  1. HANDLE CreateFile(  
  2.   
  3.    PCTSTR pszName,  
  4.   
  5.    DWORD dwDesiredAccess,  
  6.   
  7.    DWORD dwShareMode,  
  8.   
  9.    PSECURITY_ATTRIBUTES psa,  
  10.   
  11.    DWORD dwCreationDisposition,  
  12.   
  13.    DWORD dwFlagsAndAttributes,  
  14.   
  15.    HANDLE hFileTemplate);  


 

    psaName既表示設(shè)備類型也表示該類設(shè)備一個(gè)實(shí)例,。

 

    dwDesiredAccess用來指定我們以何種方式和設(shè)備通信??梢詡魅胍韵轮担?/span>

 

    0                           不允許讀寫,,但可以改變?cè)O(shè)備屬性。

    GENERIC_READ                只讀訪問

    GENERIC_WRITE               只寫訪問

    GENERIC_READ|GENERIC_WRITE  讀寫訪問,。

 

    dwSharedMode用來指定共享權(quán)限:

 

    0                                獨(dú)占對(duì)設(shè)備的訪問,。如果設(shè)備已經(jīng)打開,我們    的CreateFile會(huì)失敗。

 

    FILE_SHARE_READ                  只讀共享,,不允許修改內(nèi)容,。如果設(shè)備已經(jīng)以寫入或獨(dú)占方式打開,我們的CreateFile會(huì)失敗,。

 

    FILE_SHARE_WRITE                 寫共享,,不允許讀取內(nèi)容。如果設(shè)備已經(jīng)以讀取或獨(dú)占方式打開,,我們的CreateFile會(huì)失敗,。

 

    FILE_SHARE_READ|FILE_SHARE_WRITE  不關(guān)心向設(shè)備讀還是寫數(shù)據(jù)。如果設(shè)備已經(jīng)以獨(dú)占方式打開,,我們的CreateFile會(huì)失敗,。

 

    FIEL_SHARE_DELETE                 先將文件標(biāo)記待刪除,所有對(duì)該文件引用的句柄都關(guān)閉之后,,才將其真正的刪除,。

 

    psa指向一個(gè)PSECURITY_ATTRIBUTES結(jié)構(gòu),用來指定安全屬性,。只有當(dāng)我們?cè)诰邆浒踩缘奈募到y(tǒng)中,,如NTFS中創(chuàng)建文件時(shí)才會(huì)用到此結(jié)構(gòu)。在其他情況下都只需要傳入NULL就可以了,,此時(shí)會(huì)用默認(rèn)的安全屬性來創(chuàng)建文件,,并且返回的句柄是不可繼承的。

 

    dwCreationDisposition參數(shù)對(duì)文件的含義更重大,。它可以是以下值:

 

    CREATE_NEW        創(chuàng)建一個(gè)新文件,。如果同名文件存在則失敗。

    CREATE_ALWAYS     文件同名文件存在與否都創(chuàng)建文件,。存在時(shí)會(huì)覆蓋,。

    OPEN_EXISTING     打開一個(gè)已存在文件。如不存在,,則失敗,。

    OPEN_ALWAYS        打開一個(gè)已存在文件。如不存在,,則創(chuàng)建,。

    TRUNCATE_EXISTING 打開一個(gè)已存在文件,將文件大小截?cái)酁?span style="font-family:Times New Roman">0,如果不存在則調(diào)用失敗,。

 

    dwFlagsAndAttributes有兩個(gè)用途:一,,允許我們?cè)O(shè)置一些標(biāo)志微調(diào)與設(shè)備的通信。二:如果設(shè)備是文件,,還可以設(shè)置文件屬性,。這些標(biāo)志大多數(shù)是一些信號(hào),用來告訴系統(tǒng)我們打算以何種方式來訪問設(shè)備,這樣系統(tǒng)就可以對(duì)緩存算法進(jìn)行優(yōu)化,。此處不再介紹。

 

     hFileTemplate,,既可以標(biāo)識(shí)一個(gè)已經(jīng)打開的文件句柄,,也可以是NULL。如果是一個(gè)文件句柄,,那么CreateFile會(huì)完全忽略dwFlagsAndAttributes參數(shù),,轉(zhuǎn)而使用hFileTemplate標(biāo)識(shí)的文件屬性。此時(shí),,hFileTemplate標(biāo)識(shí)的文件句柄必須是一個(gè)用GENERIC_READ標(biāo)志打開的文件,。

 

    CreateFile成功的創(chuàng)建或打開設(shè)備那會(huì)返回設(shè)備句柄。否則返回INVALID_HANDLE_VALUE,。一定要注意返回值不是NULL哦,。

 

    Windows在設(shè)計(jì)時(shí)使用了64位來表示文件大小。但是64位需要分兩個(gè)32位值來傳入,。實(shí)際上在日常工作中還有使用大于4G的文件,。高32位在大多數(shù)情況下都會(huì)是0。

GetFileSizeEx用于得到文件大小,。

 

  1. BOOL GetFileSizeEx(  
  2.   
  3.    HANDLE hFile,  
  4.   
  5.      PLARGE_INTEGER pliFileSize);  
  6.   
  7.       


 

    hFile表示一個(gè)一打開文件的句柄,。

 

    pliFileSize表示文件大小。定義如下:

  1. typedef union _LARGE_INTEGER  
  2.   
  3. {  
  4.   
  5. struct  
  6.   
  7. {  
  8.   
  9.    DWORD LowPart;  
  10.   
  11.    LONG HighPart;  
  12.   
  13. };  
  14.   
  15. LONGLONG QuadPart;  
  16.   
  17. }LARGE_INTEGER,*PLARGE_INTEGER;  


 

    它允許我們以一個(gè)64位有符號(hào)數(shù)或者是兩個(gè)32位值來表示一個(gè)64位數(shù),。

 

    另外一個(gè)很重要的函數(shù)是GetCompressedFileSize

  1. DWORD GetCompressedFileSize(  
  2.   
  3. PCTSTR pszFileName,  
  4.   
  5. PDWORD pdwFileSizeHigh);  


 

這個(gè)函數(shù)返回文件物理大小,,而GetFileSizeEx是返回文件邏輯大小。

 

CreateFile會(huì)創(chuàng)建一個(gè)文件內(nèi)核對(duì)象來管理文件,。返回的句柄就是對(duì)該文件內(nèi)核對(duì)象的引用,。在這個(gè)內(nèi)核對(duì)象中有一個(gè)文件指針,它表示應(yīng)該在哪里執(zhí)行下一次讀取或?qū)懭氩僮?。開始時(shí)它的值是0,。

 

SetFilePointerEx可以通過操作文件指針實(shí)現(xiàn)隨機(jī)訪問文件。

  1. BOOL SetFilePointerEx(  
  2.   
  3.    HANDLE hFile,  
  4.   
  5.    LARGE_INTEGER liDistanceToMove,  
  6.   
  7.    PLARGE_INTEGER pliNewFilePointer,  
  8.   
  9.   DWORD dwMoveMethod);  


 

    hFile表示我們要操作的文件指針,。

 

liDistanceToMove指定我們要移動(dòng)文件指針的字節(jié)數(shù),。系統(tǒng)會(huì)把我們指定的值與文件指針的當(dāng)前值相加。傳入負(fù)值是合法的,。

 

    dwMoveMethod指定移動(dòng)文件指針的起始位置,。

 

FILE_BEGIN      從文件開頭開始。

FILE_CURRENT   從當(dāng)前位置開始,。

FILE_END       從文件末尾,。

 

pliNewFilePointer返回文件指針的新值。

 

設(shè)置文件尾。

  1. BOOL SetEndOfFile(HANDLE hFile);  


 

此函數(shù)會(huì)根據(jù)文件對(duì)象當(dāng)前的文件指針當(dāng)前所在的位置,,截?cái)辔募?。如果想要將文件設(shè)置為2k,可以這樣:

 

  1. LARGE_INTEGER li;  
  2.   
  3. li.QuadPart=2048;  
  4.   
  5. SetFilePointerEx(hFile,li,NULL,FILE_BEGIN);  
  6.   
  7. SetEndOfFile(hFile);  
  8.   
  9. CloseHandle(hFile);  


 

ReadFile和WriteFile

  1. BOOL ReadFile(  
  2.   
  3.    HANDLE hFile,  
  4.   
  5.    PVOID pvBuffer,  
  6.   
  7.    DWORD nNumBytesToRead,  
  8.   
  9.    PDWORD pdwNumBytes,  
  10.   
  11.    OVERLAPPED*pOverlapped);  
  12.   
  13. BOOL WriteFile(  
  14.   
  15.      HANDLE hFile,  
  16.   
  17.      CONST VOID *pvBuffer,  
  18.   
  19.      DWORD nNumBytesToWrite,  
  20.   
  21.      PDWORD pdwNumbytes,  
  22.   
  23.      OVERLAPPED*pOverlapped);  


 

hFile表示我們要訪問的設(shè)備,。調(diào)用CreateFile打開設(shè)備時(shí)一定不能指定FILE_FLAG_OVERLAPPED標(biāo)志,,否則系統(tǒng)認(rèn)為我們想要與該設(shè)備執(zhí)行異步IO

 

pvBuffer指向一個(gè)緩存,,函數(shù)會(huì)把設(shè)備數(shù)據(jù)讀取到該緩存中或者把該緩存的數(shù)據(jù)寫入設(shè)備,。

 

nNumbytesToRead和nNumBytesToWrite分別告訴ReadFileWriteFile要從設(shè)備讀取或?qū)懭攵嗌僮止?jié)。

 

pdwNumBytes返回讀取的字節(jié)或向設(shè)備寫入的字節(jié),。

 

在執(zhí)行同步IO時(shí),,最后一個(gè)參數(shù)pOverlapped應(yīng)該被設(shè)為NULL

 

ReadFile和WriteFile執(zhí)行成功后都返回true,。

 

FlushBuffers將數(shù)據(jù)刷新至設(shè)備,。

  1. BOOL FlushFileBuffers(HANDLE hFile);  


 

該函數(shù)會(huì)強(qiáng)制將hFile參數(shù)所標(biāo)識(shí)的設(shè)備相關(guān)聯(lián)的所有緩存寫入設(shè)備。

 

同步IO很容易使用,,但是它會(huì)阻塞線程,。比如:如果由于CreateFile正在執(zhí)行同步IO操作而導(dǎo)致線程被阻塞,那么該線程的其他操作都會(huì)得不到處理,。更嚴(yán)重的情況是會(huì)導(dǎo)致應(yīng)用程序停止響應(yīng),。Windows允許我們?nèi)∠付ň€程尚未完成的同步IO請(qǐng)求。

 

  1. BOOL CancelSynchronousIo(HANDLE hThread);  


 

hThread標(biāo)識(shí)由于等待同步IO完成而被掛起的線程句柄,。這個(gè)句柄必須是使用THREAD_TERMINATE訪問權(quán)限創(chuàng)建的,。否則,函數(shù)會(huì)失敗,。GetLastError會(huì)返回ERROR_ACCESSS_DENIED,。

 

我們自己創(chuàng)建的線程的安全屬性是THREAD_ACCESS的,其中包括THREAD_TERMINATE,。如果我們利用線程池,,那么我們必須調(diào)用OpenThread來得到當(dāng)前線程標(biāo)識(shí)符對(duì)應(yīng)的線程句柄,同時(shí)傳入THREAD_TERMINATE,。

 

CanelSynchronousIo會(huì)將等待IO完成而被掛起的線程喚醒,。如果線程并不是因?yàn)橐却O(shè)備響應(yīng)而被掛起,函數(shù)返回false,。GetLastError返回ERROR_NOT_FOUND,。

 

即便如此,為了創(chuàng)建響應(yīng)性好的應(yīng)用程序我們應(yīng)該盡可能的執(zhí)行異步IO操作,。下一篇博文會(huì)有詳細(xì)介紹,。

 

 

                                本博文參考自《Windows核心編程》第五版 第二部分,。如有紕漏,請(qǐng)不吝賜教,!

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn),。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式,、誘導(dǎo)購買等信息,謹(jǐn)防詐騙,。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,,請(qǐng)點(diǎn)擊一鍵舉報(bào),。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多