|
Win 32系統(tǒng)把文件的概念進行了擴展。無論是文件、通信設備、命名管道、郵件槽、磁盤、還是控制臺,都是用API函數(shù)CreateFile來打開或創(chuàng)建的。該函數(shù)的聲明為:
HANDLE CreateFile
如果調用成功,那么該函數(shù)返回文件的句柄,如果調用失敗,則函數(shù)返回INVALID_HANDLE_VALUE。 調用GetCommState函數(shù)可以獲得串口的配置,該函數(shù)把當前配置填充到一個DCB結構中。一般在用CreateFile打開串行口后,可以調用GetCommState函數(shù)來獲取串行口的初始配置。要修改串行口的配置,應該先修改DCB結構,然后再調用SetCommState函數(shù)用指定的DCB結構來設置串行口。 除了在DCB中的設置外,程序一般還需要設置I/O緩沖區(qū)的大小和超時。Windows用I/O緩沖區(qū)來暫存串行口輸入和輸出的數(shù)據(jù),如果通信的速率較高,則應該設置較大的緩沖區(qū)。調用SetupComm函數(shù)可以設置串行口的輸入和輸出緩沖區(qū)的大小。 在用ReadFile和WriteFile讀寫串行口時,需要考慮超時問題。如果在指定的時間內沒有讀出或寫入指定數(shù)量的字符,那么ReadFile或WriteFile的操作就會結束。要查詢當前的超時設置應調用GetCommTimeouts函數(shù),該函數(shù)會填充一個COMMTIMEOUTS結構。調用SetCommTimeouts可以用某一個COMMTIMEOUTS結構的內容來設置超時。 有兩種超時:間隔超時和總超時。間隔超時是指在接收時兩個字符之間的最大時延,總超時是指讀寫操作總共花費的最大時間。寫操作只支持總超時,而讀操作兩種超時均支持。用COMMTIMEOUTS結構可以規(guī)定讀/寫操作的超時,該結構的定義為: typedef struct _COMMTIMEOUTS COMMTIMEOUTS結構的成員都以毫秒為單位。總超時的計算公式是: 總超時=時間系數(shù)×要求讀/寫的字符數(shù) + 時間常量 可以看出,間隔超時和總超時的設置是不相關的,這可以方便通信程序靈活地設置各種超時。 如果所有寫超時參數(shù)均為0,那么就不使用寫超時。如果ReadIntervalTimeout為0,那么就不使用讀間隔超時,如果ReadTotalTimeoutMultiplier和ReadTotalTimeoutConstant都為0,則不使用讀總超時。如果讀間隔超時被設置成MAXDWORD并且兩個讀總超時為0,那么在讀一次輸入緩沖區(qū)中的內容后讀操作就立即完成,而不管是否讀入了要求的字符。 在用重疊方式讀寫串行口時,雖然ReadFile和WriteFile在完成操作以前就可能返回,但超時仍然是起作用的。在這種情況下,超時規(guī)定的是操作的完成時間,而不是ReadFile和WriteFile的返回時間。在用ReadFile和WriteFile讀寫串行口時,既可以同步執(zhí)行,也可以重疊(異步)執(zhí)行。在同步執(zhí)行時,函數(shù)直到操作完成后才返回。這意味著在同步執(zhí)行時線程會被阻塞,從而導致效率下降。在重疊執(zhí)行時,即使操作還未完成,調用的函數(shù)也會立即返回。費時的I/O操作在后臺進行,這樣線程就可以干別的事情。例如,線程可以在不同的句柄上同時執(zhí)行I/O操作,甚至可以在同一句柄上同時進行讀寫操作?!爸丿B”一詞的含義就在于此。 ReadFile函數(shù)只要在串行口輸入緩沖區(qū)中讀入指定數(shù)量的字符,就算完成操作。而WriteFile函數(shù)不但要把指定數(shù)量的字符拷入到輸出緩沖中,而且要等這些字符從串行口送出去后才算完成操作。 ReadFile和WriteFile函數(shù)是否為執(zhí)行重疊操作是由CreateFile函數(shù)決定的。如果在調用CreateFile創(chuàng)建句柄時指定了FILE_FLAG_OVERLAPPED標志,那么調用ReadFile和WriteFile對該句柄進行的讀寫操作就是重疊的,如果未指定重疊標志,則讀寫操作是同步的。 函數(shù)ReadFile和WriteFile的參數(shù)和返回值很相似。這里僅列出ReadFile函數(shù)的聲明: BOOL ReadFile
需要注意的是如果該函數(shù)因為超時而返回,那么返回值是TRUE。參數(shù)lpOverlapped在重疊操作時應該指向一個OVERLAPPED結構,如果該參數(shù)為NULL,那么函數(shù)將進行同步操作,而不管句柄是否是由FILE_FLAG_OVERLAPPED標志建立的。 當ReadFile和WriteFile返回FALSE時,不一定就是操作失敗,線程應該調用GetLastError函數(shù)分析返回的結果。例如,在重疊操作時如果操作還未完成函數(shù)就返回,那么函數(shù)就返回FALSE,而且GetLastError函數(shù)返回ERROR_IO_PENDING。 在使用重疊I/O時,線程需要創(chuàng)建OVERLAPPED結構以供讀寫函數(shù)使用。OVERLAPPED結構最重要的成員是hEvent,hEvent是一個事件對象句柄,線程應該用CreateEvent函數(shù)為hEvent成員創(chuàng)建一個手工重置事件,hEvent成員將作為線程的同步對象使用。如果讀寫函數(shù)未完成操作就返回,就那么把hEvent成員設置成無信號的。操作完成后(包括超時),hEvent會變成有信號的。 如果GetLastError函數(shù)返回ERROR_IO_PENDING,則說明重疊操作還為完成,線程可以等待操作完成。有兩種等待辦法:一種辦法是用象WaitForSingleObject這樣的等待函數(shù)來等待OVERLAPPED結構的hEvent成員,可以規(guī)定等待的時間,在等待函數(shù)返回后,調用GetOverlappedResult。另一種辦法是調用GetOverlappedResult函數(shù)等待,如果指定該函數(shù)的bWait參數(shù)為TRUE,那么該函數(shù)將等待OVERLAPPED結構的hEvent 事件。GetOverlappedResult可以返回一個OVERLAPPED結構來報告包括實際傳輸字節(jié)在內的重疊操作結果。 如果規(guī)定了讀/寫操作的超時,那么當超過規(guī)定時間后,hEvent成員會變成有信號的。因此,在超時發(fā)生后,WaitForSingleObject和GetOverlappedResult都會結束等待。WaitForSingleObject的dwMilliseconds參數(shù)會規(guī)定一個等待超時,該函數(shù)實際等待的時間是兩個超時的最小值。注意GetOverlappedResult不能設置等待的時限,因此如果hEvent成員無信號,則該函數(shù)將一直等待下去。 在調用ReadFile和WriteFile之前,線程應該調用ClearCommError函數(shù)清除錯誤標志。該函數(shù)負責報告指定的錯誤和設備的當前狀態(tài)。 調用PurgeComm函數(shù)可以終止正在進行的讀寫操作,該函數(shù)還會清除輸入或輸出緩沖區(qū)中的內容 |
|
|
來自: _小女子_ > 《windows編程》