摘要:介紹了一種Linux下用多線程編程實現嵌入式設備串口通信的方法。重點分析通信線程類的設計和實現過程,以及Linux下共享數據區的訪問技巧。
關鍵詞:嵌入式;編程;多線程;共享數據區;互斥鎖。
Implementing the communication of serial ports using multithread under Linux
on embedded devices
DU Zhixiu ZHENG Haixin
(Department of Optical and Electronic Equipments, the Academy of Equipment Command &Technology, Beijing 101400,China)
Abstract: The paper introduces the method to implement the communication of serial ports using multithread under Linux. Its main points lie on the design and implement of customizing thread class, and how to access the shared memory under Linux.
Key words: embedded; programming; multithread; shared data memory; mutex lock.
1. 引言
在某嵌入式設備開發項目中,根據系統總體設計,要求ARM主處理器的三個串口能同時工作以完成必須的通信功能。其中串口1和串口2用于接收數據采集結果,串口3實現數據聯網,通信程序要求在Linux下用C++編程實現。針對上述功能需求,我們經過認真研究和編程測試,形成一個實用的解決方案,即采取Linux下多線程編程來實現串口通信,以便快速響應外部的多輸入量,下面具體介紹設計思路和技巧。
2.Linux下串口通信的多線程實現
2.1 通信線程類
根據主處理器三個串口的通信功能需求,我們擬定由串口1接收A類采集數據,之后放入本端口對應的接收隊列中。數據分析模塊從該接收隊列獲取數據進行數據分析和處理。主程序設置A類數據采集模式的各種命令先保存在串口1發送隊列中,通信模塊再擇機發送出去。串口2依次主動呼叫各下位機,要求傳送B類采集數據,收到數據后保存到串口2的接收數據緩沖隊列中。顯示模塊定時從該隊列中獲取數據,刷新屏幕顯示。同時打印數據和系統報警控制信息也通過串口2發送出去。對該口掛接各設備的控制命令先暫存到本端口發送隊列中,適當時機再發送。當中央主機要求聯網數據時,接收到的命令先保存到串口3接收隊列中,由主處理模塊先解析接收命令,然后根據要求將指定的數據打包并從串口3發送出去。圖1示出主處理器3個串口的使用情況和數據存儲策略,這就要求編寫Linux下運行在單處理器上的并發運行程序。我們知道,一個線程就是一個程序計數器、一個堆棧和一系列的寄存器,它對應于一個任務,故可以利用線程來分割圖1中的任務。 為此我們抽象出一個串口通信線程類ComThread,該類在實例化后利用子函數pthread_create分別創建一個新的數據接收線程和一個新的數據發送線程。pthread_create函數有四個參數:一個用來保存線程的線程變量、一個線程屬性、當線程執行時要調用的函數和一個此函數的參數。線程使用pthread_create中的參數指明要開始執行的函數,此處對應ComThread中的數據接收方法和數據發送方法。這樣以來,系統運行后三個串口各自對應一個串口通信線程對象,每個對象按不同的數據傳輸速率要求完成串口初始化設置,并創建數據接收線程和數據發送線程。正常工作時系統中共有六個數據收發線程并行執行,大大提高了嵌入式設備對外部多輸入參量的并行處理能力。
由于線程之間可以共享資源,串口通信線程類在接收和發送數據時,利用循環隊列進行數據緩沖。接收隊列和發送隊列是相互獨立的,如圖2中所示。這些數據隊列被串口通信模塊和顯示模塊共享,因此需要處理好線程之間共享數據存儲區的訪問沖突問題。
圖1. 串口使用情況圖
2.2共享數據區的訪問
POSIX提供的線程同步方法mutex,是一種簡單的加鎖方法,用來控制對共享資源的存取。它只有兩個狀態,鎖定和非鎖定。本項目的發送隊列,顯示模塊線程要對其執行發送數據寫操作,通信模塊數據發送線程要從中讀取待發送數據或命令,任何一方在訪問它之前,都要使用子函數pthread_mutex_lock加互斥鎖,以防訪問沖突造成死鎖現象。訪問結束后用pthread_mutex_unlock解鎖,讓出對共享數據區的訪問權限。對接收隊列的操作與此類似,如圖2中所示。
