本章我們將以工業控制和嵌入式系統中運用極為廣泛的串列埠通訊為例講述多執行緒的典型應用。
而網路通訊也是多執行緒應用最廣泛的領域之一,所以本章的最後一節也將對多執行緒網路通訊進行簡短的描述。
1.串列埠通訊
在工業控制系統中,工控機(一般都基於pc windows平台)經常需要與微控制器通過串列埠進行通訊。因此,操作和使用pc的串列埠成為大多數微控制器、嵌入式系統領域工程師必須具備的能力。
串列埠的使用需要通過三個步驟來完成的:
(1) 開啟通訊埠;
(2) 初始化串列埠,設定波特率、資料位、停止位、奇偶校驗等引數。為了給讀者乙個直觀的印象,下圖從windows的"控制面板->系統->裝置管理器->通訊埠(com1)"開啟com的設定視窗:
(3) 讀寫串列埠。
在win32平台下,對通訊埠進行操作跟基本的檔案操作一樣。
建立/開啟com資源
下列函式如果呼叫成功,則返回乙個標識通訊埠的控制代碼,否則返回-1:
hadle createfile(pctstr lpfilename, //通訊埠名,如"com1"
word dwdesiredaccess, //對資源的訪問型別
word dwsharemode, //指定共享模式,com不能共享,該引數為0
psecurity_attributes lpsecurityattributes,
//安全描述符指標,可為null
word dwcreationdisposition, //建立方式
word dwflagsandattributes, //檔案屬性,可為null
handle htemplatefile //模板檔案控制代碼,置為null
);獲得/設定com屬性
下列函式可以獲得com口的裝置控制塊,從而獲得相關引數:
bool winapi getcommstate(
handle hfile, //標識通訊埠的控制代碼
lpdcb lpdcb //指向乙個裝置控制塊(dcb結構)的指標
);如果要調整通訊埠的引數,則需要重新配置裝置控制塊,再用win32 api setcommstate()函式進行設定:
bool setcommstate(
handle hfile, //標識通訊埠的控制代碼
lpdcb lpdcb //指向乙個裝置控制塊(dcb結構)的指標
);dcb結構包含了串列埠的各項引數設定,如下:
typedef struct _dcb
dcb;
讀寫串列埠
在讀寫串列埠之前,還要用purgecomm()函式清空緩衝區,並用setcommmask ()函式設定事件掩模來監視指定通訊埠上的事件,其原型為:
bool setcommmask(
handle hfile, //標識通訊埠的控制代碼
dword dwevtmask //能夠使能的通訊事件
);串列埠上可能發生的事件如下表所示:
值 事件描述
ev_break
a break was detected on input.
ev_cts
the cts (clear-to-send) signal changed state.
ev_dsr
the dsr(data-set-ready) signal changed state.
ev_err
a line-status error occurred. line-status errors are ce_frame, ce_overrun, and ce_rxparity.
ev_ring
a ring indicator was detected.
ev_rlsd
the rlsd (receive-line-signal-detect) signal changed state.
ev_rxchar
a character was received and placed in the input buffer.
ev_rxflag
ev_txempty
the last character in the output buffer was sent.
2.工程例項
下面我們用第1節所述api實現乙個多執行緒的串列埠通訊程式。這個例子工程(工程名為multithreadcom)的介面很簡單,如下圖所示:
兩個串列埠com1和com2對應的執行緒處理函式等待串列埠上發生事件,並根據事件型別和自身緩衝區是否有資料要傳送進行相應的處理,其源**為:
dword winapi com1threadprocess(hwnd hwnd//主視窗控制代碼)
else
break;
case ev_rxchar:
if (com1data.wrxpos < com1data.wrxlen)
break;}}
}}return true;
}dword winapi com2threadprocess(hwnd hwnd //主視窗控制代碼)
else
break;
case ev_rxchar:
if (com2data.wrxpos < com2data.wrxlen)
break;}}
}return true;
}執行緒控制函式中所操作的com1data和com2data是與串列埠對應的資料結構struct tagserialport的例項,這個資料結構是:
typedef struct tagserialport
serialport, * lpserialport;
下列三個函式用於對串列埠線程進行啟動、掛起和恢復:
//// start comm watching
//bool cserialport::startmonitoring()
//// restart the comm thread
//bool cserialport::restartmonitoring()
//// suspend the comm thread
//bool cserialport::stopmonitoring()
3.3.5控制介面
應用程式設計師使用下列一組public函式可以獲取串列埠的dcb及串列埠上發生的事件:
//// return the device control block
//dcb cserialport::getdcb()
//// return the communication event masks
//dword cserialport::getcommevents()
仔細分析remon spekreijse的cserialport類對我們理解多執行緒及其同步機制是大有益處的,從我們可以獲取cserialport類的介紹與工程例項。另外,電子工業出版社《visual c++/turbo c串列埠通訊程式設計實踐》一書的作者龔建偉也編寫了乙個使用cserialport類的例子,可以從獲得詳情。
4.多執行緒網路通訊
在網路通訊中使用多執行緒主要有兩種途徑,即主監控執行緒和執行緒池。
4.1主監控執行緒
這種方式指的是程式中使用乙個主線程監控某特定埠,一旦在這個埠上發生連線請求,則主監控執行緒動態使用createthread派生出新的子執行緒處理該請求。主線程在派生子執行緒後不再對子執行緒加以控制和排程,而由子執行緒獨自和客戶方發生連線並處理異常。
使用這種方法的優點是:
(1)可以較快地實現原型設計,尤其在使用者數目較少、連線保持時間較長時有表現較好;
(2)主線程不與子執行緒發生通訊,在一定程度上減少了系統資源的消耗。
其缺點是:
(1)生成和終止子執行緒的開銷比較大;
(2)對遠端使用者的控制較弱。
這種多執行緒方式總的特點是"動態生成,靜態排程"。
4.2執行緒池
這種方式指的是主線程在初始化時靜態地生成一定數量的懸掛子執行緒,放置於執行緒池中。隨後,主線程將對這些懸掛子執行緒進行動態排程。一旦客戶發出連線請求,主線程將從執行緒池中查詢乙個懸掛的子執行緒:
(1)如果找到,主線程將該連線分配給這個被發現的子執行緒。子執行緒從主線程處接管該連線,並與使用者通訊。當連線結束時,該子執行緒將自動懸掛,並進人執行緒池等待再次被排程;
(2)如果當前已沒有可用的子執行緒,主線程將通告發起連線的客戶。
使用這種方法進行設計的優點是:
(1)主線程可以更好地對派生的子執行緒進行控制和排程;
(2)對遠端使用者的監控和管理能力較強。
雖然主線程對子執行緒的排程要消耗一定的資源,但是與主監控執行緒方式中派生和終止執行緒所要耗費的資源相比,要少很多。因此,使用該種方法設計和實現的系統在客戶端連線和終止變更頻繁時有上佳表現。
這種多執行緒方式總的特點是"靜態生成,動態排程"。
深入淺出Win32多執行緒程式設計之綜合例項 1
本章我們將以工業控制和嵌入式系統中運用極為廣泛的串列埠通訊為例講述多執行緒的典型應用。而網路通訊也是多執行緒應用最廣泛的領域之一,所以本章的最後一節也將對多執行緒網路通訊進行簡短的描述。1.串列埠通訊在工業控制系統中,工控機 一般都基於pc windows平台 經常需要與微控制器通過串列埠進行通訊。...
深入淺出Win32多執行緒設計之MFC的多執行緒(2)
2.執行緒間通訊 mfc中定義了繼承自csyncobject類的ccriticalsection ccevent cmutex csemaphore類封裝和簡化了win32 api所提供的臨界區 事件 互斥和訊號量。使用這些同步機制,必須包含 afxmt.h 標頭檔案。下圖給出了類的繼承關係 作為c...
深入淺出VC 串列埠程式設計之基於Win32 API
1 api描述 在win32 api中,串列埠使用檔案方式進行訪問,其操作的api基本上與檔案操作的api一致。開啟串列埠 win32 中用於開啟串列埠的api 函式為createfile,其原型為 例如,以下程式用於以同步讀寫方式開啟串列埠com1 handle hcom dword dwerro...