乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      串行通信與重疊(異步)I/O

       _小女子_ 2011-12-15
      Win 32系統(tǒng)把文件的概念進(jìn)行了擴(kuò)展。無論是文件、通信設(shè)備、命名管道、郵件槽、磁盤、還是控制臺(tái),都是用API函數(shù)CreateFile來打開或創(chuàng)建的。該函數(shù)的聲明為:

        HANDLE CreateFile
        (
          LPCTSTR lpFileName,             // 文件名 
          DWORD dwDesiredAccess,           // 訪問模式 
          DWORD dwShareMode,             // 共享模式 
          LPSECURITY_ATTRIBUTES lpSecurityAttributes, // 通常為NULL
          DWORD dwCreationDistribution,        // 創(chuàng)建方式 
          DWORD dwFlagsAndAttributes,         // 文件屬性和標(biāo)志
          HANDLE hTemplateFile            // 臨時(shí)文件的句柄,通常為NULL 
        );

        如果調(diào)用成功,那么該函數(shù)返回文件的句柄,如果調(diào)用失敗,則函數(shù)返回INVALID_HANDLE_VALUE。
        在打開通信設(shè)備句柄后,常常需要對(duì)串行口進(jìn)行一些初始化工作。這需要通過一個(gè)DCB結(jié)構(gòu)來進(jìn)行。DCB結(jié)構(gòu)包含了諸如波特率、每個(gè)字符的數(shù)據(jù)位數(shù)、奇偶校驗(yàn)和停止位數(shù)等信息。在查詢或配置置串行口的屬性時(shí),都要用DCB結(jié)構(gòu)來作為緩沖區(qū)。

        調(diào)用GetCommState函數(shù)可以獲得串口的配置,該函數(shù)把當(dāng)前配置填充到一個(gè)DCB結(jié)構(gòu)中。一般在用CreateFile打開串行口后,可以調(diào)用GetCommState函數(shù)來獲取串行口的初始配置。要修改串行口的配置,應(yīng)該先修改DCB結(jié)構(gòu),然后再調(diào)用SetCommState函數(shù)用指定的DCB結(jié)構(gòu)來設(shè)置串行口。

        除了在DCB中的設(shè)置外,程序一般還需要設(shè)置I/O緩沖區(qū)的大小和超時(shí)。Windows用I/O緩沖區(qū)來暫存串行口輸入和輸出的數(shù)據(jù),如果通信的速率較高,則應(yīng)該設(shè)置較大的緩沖區(qū)。調(diào)用SetupComm函數(shù)可以設(shè)置串行口的輸入和輸出緩沖區(qū)的大小。

        在用ReadFile和WriteFile讀寫串行口時(shí),需要考慮超時(shí)問題。如果在指定的時(shí)間內(nèi)沒有讀出或?qū)懭胫付〝?shù)量的字符,那么ReadFile或WriteFile的操作就會(huì)結(jié)束。要查詢當(dāng)前的超時(shí)設(shè)置應(yīng)調(diào)用GetCommTimeouts函數(shù),該函數(shù)會(huì)填充一個(gè)COMMTIMEOUTS結(jié)構(gòu)。調(diào)用SetCommTimeouts可以用某一個(gè)COMMTIMEOUTS結(jié)構(gòu)的內(nèi)容來設(shè)置超時(shí)。

        有兩種超時(shí):間隔超時(shí)和總超時(shí)。間隔超時(shí)是指在接收時(shí)兩個(gè)字符之間的最大時(shí)延,總超時(shí)是指讀寫操作總共花費(fèi)的最大時(shí)間。寫操作只支持總超時(shí),而讀操作兩種超時(shí)均支持。用COMMTIMEOUTS結(jié)構(gòu)可以規(guī)定讀/寫操作的超時(shí),該結(jié)構(gòu)的定義為:

        typedef struct _COMMTIMEOUTS
        { 
          DWORD ReadIntervalTimeout;     // 讀間隔超時(shí)
          DWORD ReadTotalTimeoutMultiplier;  // 讀時(shí)間系數(shù)
          DWORD ReadTotalTimeoutConstant;   // 讀時(shí)間常量
          DWORD WriteTotalTimeoutMultiplier; // 寫時(shí)間系數(shù)
          DWORD WriteTotalTimeoutConstant;  // 寫時(shí)間常量
        } COMMTIMEOUTS,*LPCOMMTIMEOUTS;

        COMMTIMEOUTS結(jié)構(gòu)的成員都以毫秒為單位。總超時(shí)的計(jì)算公式是: 總超時(shí)=時(shí)間系數(shù)×要求讀/寫的字符數(shù) + 時(shí)間常量
        例如,如果要讀入10個(gè)字符,那么讀操作的總超時(shí)的計(jì)算公式為: 讀總超時(shí)=ReadTotalTimeoutMultiplier×10 + ReadTotalTimeoutConstant

        可以看出,間隔超時(shí)和總超時(shí)的設(shè)置是不相關(guān)的,這可以方便通信程序靈活地設(shè)置各種超時(shí)。

        如果所有寫超時(shí)參數(shù)均為0,那么就不使用寫超時(shí)。如果ReadIntervalTimeout為0,那么就不使用讀間隔超時(shí),如果ReadTotalTimeoutMultiplier和ReadTotalTimeoutConstant都為0,則不使用讀總超時(shí)。如果讀間隔超時(shí)被設(shè)置成MAXDWORD并且兩個(gè)讀總超時(shí)為0,那么在讀一次輸入緩沖區(qū)中的內(nèi)容后讀操作就立即完成,而不管是否讀入了要求的字符。

        在用重疊方式讀寫串行口時(shí),雖然ReadFile和WriteFile在完成操作以前就可能返回,但超時(shí)仍然是起作用的。在這種情況下,超時(shí)規(guī)定的是操作的完成時(shí)間,而不是ReadFile和WriteFile的返回時(shí)間。在用ReadFile和WriteFile讀寫串行口時(shí),既可以同步執(zhí)行,也可以重疊(異步)執(zhí)行。在同步執(zhí)行時(shí),函數(shù)直到操作完成后才返回。這意味著在同步執(zhí)行時(shí)線程會(huì)被阻塞,從而導(dǎo)致效率下降。在重疊執(zhí)行時(shí),即使操作還未完成,調(diào)用的函數(shù)也會(huì)立即返回。費(fèi)時(shí)的I/O操作在后臺(tái)進(jìn)行,這樣線程就可以干別的事情。例如,線程可以在不同的句柄上同時(shí)執(zhí)行I/O操作,甚至可以在同一句柄上同時(shí)進(jìn)行讀寫操作?!爸丿B”一詞的含義就在于此。

        ReadFile函數(shù)只要在串行口輸入緩沖區(qū)中讀入指定數(shù)量的字符,就算完成操作。而WriteFile函數(shù)不但要把指定數(shù)量的字符拷入到輸出緩沖中,而且要等這些字符從串行口送出去后才算完成操作。

        ReadFile和WriteFile函數(shù)是否為執(zhí)行重疊操作是由CreateFile函數(shù)決定的。如果在調(diào)用CreateFile創(chuàng)建句柄時(shí)指定了FILE_FLAG_OVERLAPPED標(biāo)志,那么調(diào)用ReadFile和WriteFile對(duì)該句柄進(jìn)行的讀寫操作就是重疊的,如果未指定重疊標(biāo)志,則讀寫操作是同步的。

        函數(shù)ReadFile和WriteFile的參數(shù)和返回值很相似。這里僅列出ReadFile函數(shù)的聲明:

        BOOL ReadFile
        (
          HANDLE hFile,         // 文件句柄
          LPVOID lpBuffer,       // 讀緩沖區(qū)
          DWORD nNumberOfBytesToRead,  // 要求讀入的字節(jié)數(shù) 
          LPDWORD lpNumberOfBytesRead, // 實(shí)際讀入的字節(jié)數(shù)
          LPOVERLAPPED lpOverlapped   // 指向一個(gè)OVERLAPPED結(jié)構(gòu)
        );                //若返回TRUE則表明操作成功

       

        需要注意的是如果該函數(shù)因?yàn)槌瑫r(shí)而返回,那么返回值是TRUE。參數(shù)lpOverlapped在重疊操作時(shí)應(yīng)該指向一個(gè)OVERLAPPED結(jié)構(gòu),如果該參數(shù)為NULL,那么函數(shù)將進(jìn)行同步操作,而不管句柄是否是由FILE_FLAG_OVERLAPPED標(biāo)志建立的。

        當(dāng)ReadFile和WriteFile返回FALSE時(shí),不一定就是操作失敗,線程應(yīng)該調(diào)用GetLastError函數(shù)分析返回的結(jié)果。例如,在重疊操作時(shí)如果操作還未完成函數(shù)就返回,那么函數(shù)就返回FALSE,而且GetLastError函數(shù)返回ERROR_IO_PENDING。

        在使用重疊I/O時(shí),線程需要?jiǎng)?chuàng)建OVERLAPPED結(jié)構(gòu)以供讀寫函數(shù)使用。OVERLAPPED結(jié)構(gòu)最重要的成員是hEvent,hEvent是一個(gè)事件對(duì)象句柄,線程應(yīng)該用CreateEvent函數(shù)為hEvent成員創(chuàng)建一個(gè)手工重置事件,hEvent成員將作為線程的同步對(duì)象使用。如果讀寫函數(shù)未完成操作就返回,就那么把hEvent成員設(shè)置成無信號(hào)的。操作完成后(包括超時(shí)),hEvent會(huì)變成有信號(hào)的。

        如果GetLastError函數(shù)返回ERROR_IO_PENDING,則說明重疊操作還為完成,線程可以等待操作完成。有兩種等待辦法:一種辦法是用象WaitForSingleObject這樣的等待函數(shù)來等待OVERLAPPED結(jié)構(gòu)的hEvent成員,可以規(guī)定等待的時(shí)間,在等待函數(shù)返回后,調(diào)用GetOverlappedResult。另一種辦法是調(diào)用GetOverlappedResult函數(shù)等待,如果指定該函數(shù)的bWait參數(shù)為TRUE,那么該函數(shù)將等待OVERLAPPED結(jié)構(gòu)的hEvent 事件。GetOverlappedResult可以返回一個(gè)OVERLAPPED結(jié)構(gòu)來報(bào)告包括實(shí)際傳輸字節(jié)在內(nèi)的重疊操作結(jié)果。

        如果規(guī)定了讀/寫操作的超時(shí),那么當(dāng)超過規(guī)定時(shí)間后,hEvent成員會(huì)變成有信號(hào)的。因此,在超時(shí)發(fā)生后,WaitForSingleObject和GetOverlappedResult都會(huì)結(jié)束等待。WaitForSingleObject的dwMilliseconds參數(shù)會(huì)規(guī)定一個(gè)等待超時(shí),該函數(shù)實(shí)際等待的時(shí)間是兩個(gè)超時(shí)的最小值。注意GetOverlappedResult不能設(shè)置等待的時(shí)限,因此如果hEvent成員無信號(hào),則該函數(shù)將一直等待下去。

        在調(diào)用ReadFile和WriteFile之前,線程應(yīng)該調(diào)用ClearCommError函數(shù)清除錯(cuò)誤標(biāo)志。該函數(shù)負(fù)責(zé)報(bào)告指定的錯(cuò)誤和設(shè)備的當(dāng)前狀態(tài)。

        調(diào)用PurgeComm函數(shù)可以終止正在進(jìn)行的讀寫操作,該函數(shù)還會(huì)清除輸入或輸出緩沖區(qū)中的內(nèi)容

        本站是提供個(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)論公約

        類似文章 更多