物聯網的出現及迅猛發展為世界經濟帶來了新的增長點,將那些傳統的儀器設備采用統一的方式接入LAN/Internet 勢在必行。而眾多的設備采用各種串口方式進行通信,當前出現了稱為串口服務器的工具來將這些設備接入LAN/Internet,一般都采用微控制器實現,其功能比較簡單。同時由于互聯網在安全性方面存在眾多的問題,有許多儀器設備的數據關系到企業乃至國家的信息安全,因此設計與開發具備良好安全性的串口服務器極為重要,本文采用ARM9 微處理器和Linux 操作系統,設計開發了具有多用戶訪問,使用SSL 協議的安全型串口服務器。
1 硬件電路組成
所采用的主控微處理器為AT91SAM9261[2],它擴展了 DSP 指令集和Janelle java 加速器,主時鐘頻率達到190MHz,為大量復雜的運算提供了強大了支持。
同時,其眾多的外部接口包括了從UART 到USB 的廣泛支持。其自身只帶有四個UART 接口,可以直接用來做為四串口服務器使用。另外,由軟件控制的功率管理器(PMC)可以有選擇地關閉和開啟處理器核心和各種外設或降低其工作頻率,能使得系統的功耗保持在最小。
使用 DM9000A 作為以太網控制芯片,其集成10/100M 物理層接口;內部帶有16K 字節SRAM 用作接收發送的FIFO 緩存;支持8/16bit 兩種主機工作模式;支持TCP/IP 加速減輕CPU 負擔,提高整機效能。
另外做為系統必需,還包括了電源模塊、32M 的SDRAM、2G 的NAND Flash 以及4M 的Data Flash(用于存放U-boot 和Linux 內核)。系統的硬件框圖如圖1所示。
圖 1 硬件組成
2 軟件平臺構建
系統的軟件平臺基于嵌入式 Linux 操作系統,主要的工作包括引導程序的移植,嵌入式Linux 內核的編譯,及根文件系統的生成。在做這些工作之前,需要建立一個完整的交叉編譯環境,包含gcc、glibc 等等,用來在PC 機上產生ARM 處理器能執行的二進制代碼。
引導程序采用廣泛使用的U-boot,其功能強大,包含了對TFTP、NFS 以及NAND的支持。同時ATMEL發布了專門針對其產生的處理器的U-boot 修改版本,對快速的產品開發起到了很大的幫助。從其專門網站下載U-boot 源代碼,解壓生成uboot 源代碼目錄,在其中運行“make at91sam9261ek_config; make”即可生成uboot.bin 的二進制文件,通過使用ATMEL 的ISP工具將其寫入到DATA FLASH 的8000 位置,復位AT91SAM9261 之后即能看到“U-boot>”字樣的提示符,表示U-boot 運行成功。
第二步為編譯Linux 的內核,同樣有針對AT91SAM926X 型號處理器的專門修改版本,考慮系統的穩定性,采用Linux-2.6.24 的內核版本。下載之后解壓生成Linux-2.6.24 的目錄,運行“make ARCH=armCROSS_COMPILE=arm-linux-menuconfig”命令,表示使用Linux 的處理器架構為ARM,交叉編譯器的前端為“arm-linux-”,同時使用菜單的方式對Linux 進行配置,只需將其中的芯片選為AT91SAM9261 即可。此后即可用make 命令編譯生成二進制映像文件,為了讓U-boot 能向內核傳遞一些保正正確啟動的參數,二進制映像文件還需要使用U-boot 的mkImage 工具進行包裹之后才能被U-boot 使用。
下一步,還需要制作根文件系統[3],即以”/”為起點的文件系統,在PC 機上制作rootfs 目錄來模擬,在其下生成etc、bin、lib 等Linux 所需的目錄結構,使用busybox 工具在bin 目錄中生成基本命令工具集,同時將交叉編譯器所使用的glibc 的庫文件拷貝到lib目錄下,再經過對etc 目錄的配置之后,完整的嵌入式Linux 系統即構建完成。
最后,為了滿足應用軟件的需要,還需要編譯出openSSL、XML 等支持庫,將它們拷貝到根文件系統的/lib 或/usr/lib 目錄下,將來應用軟件運行時就會自動連接到這些庫調用所需要的功能。
3 軟件實現
3.1 總體架構
串口服務器的應用軟件采用C 語言進行線程化及模塊化設計,總體架構如圖2 所示。
圖 2 軟件框架
在設計中借用了Unix/Linux 的設計思想,Unix/Linux 在系統層將所有的設備及接口都視為文件,采用統一的接口規范,使得應用程序只需使用read、write等操作即可與設備進行交互,極大地方便了程序的開發及維護,同時具有極高的可擴展性。在本設計中,將串行接口以及TCP 通信采用統一的接口框架,可以帶來擴展支持更多接口的好處,比如MODBUS 總線協議,CAN 總線等等,另外SSL 也就是在這個基礎上的擴展支持。定義結構體如下:
struct Interface{
int type;
int fd; //file descriptor
int init(int num);
int (*read)(int clientfd, BufPtr buf, int size);
int (*write)(int clientfd, BufPtr buf, int size);
int (*accept)(int sockfd);
int (*disconn)(int fd);
…
}
結構體中使用了Buf 緩沖塊結構體,用來存儲接收或者發送的數據。同時定義了接口的回調函數比如讀寫,連接等操作,這些函數根據不同的接口就有不同的實現。
接口模塊與處理模塊之間采用隊列的方式進行通信,為了充分利用Linux 系統的特性,采用信號量的方式來模擬出生產者-消費者模型,當隊列為空時使得接收線程進入睡眠狀態,降低系統資源消耗。數據包處理線程負責根據轉發策略來處理來自串口或者以太網的數據、用戶的登錄以及設備配置操作等等。
3.2 多用戶支持及工作模式
為了使得多個用戶同時在不同地點都能訪問到服務器,設計了用戶管理模塊,將用戶分為兩類:一類為管理員用戶,除了對串口的通信操作之外,還可以對串口服務器進行配置操作(以太網參數,串口參數等);另一類為普通用戶,它只能與串口進行數據的通信。進行這樣的劃分之后,可以避免掉許多普通訪問者對設備進行篡改,造成不必要的故障。
每個創建的用戶都被保存在user.xml 文件當中,采用的格式如下,其中的password 節點不以明文的方式來存取,而是使用MD5 算法對“用戶名+密碼”字符串生成16 字節的摘要字串進行保存,這樣可以方式被非法獲取到密碼。
test
16 字節MD5
normal
用戶對串口的操作應是互不影響的。用戶A 對串口1 進行操作的時候,意味得用戶B 此時不能對串口1 進行操作,但可能可以對串口2 進行操作,如果串口2 處在空閑的狀態下。因此,對串口操作定義兩種工作模式:
(1)響應模式,在此模式下,定義用戶對串口(也即串口所接設備)發送請求數據和串口對用戶的請求回應數據這一過程稱為一個響應過程,響應過程過程是互斥的。響應模式可以使得多個用戶能更充分地利用串口, 當多個用戶進行相同的數據請求時,可以合成為一個請求,從而較大地提高訪問效率。
(2)獨占模式,在此模式下,串口為某用戶獨自占有,一直到其明確地釋放了該串口。這一模式的好處是如果需要長時間與串口進行通信,可以避免其它用戶的干擾。
3.3 接口模塊
接口模塊是整個系統中最重要的部分,TCP 數據的接收及串口數據的接收都依賴于它的實現,前文提到了TCP 以及串口采用統一的接口進行抽象,串口服務器的TCP 連接同時采用了C/S 模式和S/C,也即串口服務器同時以服務器的形式供上位機連接,還能以客戶端的方式主動地去連接上位機,這在服務器地IP 地址為通過DHCP 自動獲取時非常有用,因為此時上位機無從知曉串口服務器的IP 地址而無法連接。
由于要同時服務于多個用戶,同時又要隨時地接收來自串口的數據,也就是說串口服務器應該具有良好的并發性,以不至于在多個用戶同時訪問時產生瓶頸。采用Select 模型來實現I/O 的操作,該模型首先使用FD_SET 將需要偵聽的客戶fd,TCP 偵聽fd 以及串口fd 加入到偵聽集當中,然后使用函數select()偵聽,當任何一個fd 上有數據到來時馬上返回,將數據接收完成后放入接收數據隊列后返回繼續進行偵聽,流程如圖3 所示。
圖 3 select 模型流程
3.4 SSL 的擴展
針對 ARM9 的運算能力,只要求上位機對串口服務器的數字證書進行驗證,服務器證書名為server.pem,由CA 進行簽證。CA 可以是正規證書簽發機構,也可以是自已建立的非正式簽發機構。根據非對稱密碼學,CA 使用其私鑰簽名的數據證書只有其公鑰才能解密,將其公鑰及相關信息做為根證書,只要上位機保證從安全的途徑得到根證書,因為只需要一次獲取,從而不會出現中間人攻擊的情況。
因為SSL 通信是建立在TCP 協議基礎之上,可以在原socket 程序代碼之上實現SSL 程序,openSSL 很好地對SSL 進行了封裝,且在1.0 之后的版本中提供了對ARM處理器的支持,使用openSSL 對原有TCP通信代碼進行修改即可實現SSL 安全通信。修改分別針對于struct Interface 中的accept、write、read。對于SSL,它們分別指向SSLaccept、SSLdisconn、SSLwrite、SSLread,在SSLaccept 函數中,在原有TCP 連接建立之后再進行SSL 協議的握手過程,在此過程中進行服務器數字證書的驗證并交換臨時密鑰,代碼如下:
clientFd=accept(listenerFd,(struct
sockaddr *)(&tmpAddr),(socklen_t *)&len);
bio=BIO_new_socket(clientFd,BIO_NOCLOSE);
ssl=SSL_new(ctx);
SSL_set_bio(cli->ssl,cli->sbio,cli->sbio);
//SSL 握手
if(( ret=SSL_accept(cli->ssl)) <= 0 ) {
sslErr(ssl);
}
在SSLwrite 及SSLread 函數中可以簡單地將原socket 中的read 及write 函數替換為openSSL 庫中的SSL_write 和SSL_read 函數。不過對于SSLread,由于使用了select 并發模型,只要fd 上有數據出現select函數即馬上返回,而此時可能openSSL 正在進行數據解密操作,SSL_write 函數則返回錯誤的信息。對此必須對返回的錯誤進行處理,一直等到解密完成才能讀取返回:
do {
ret=SSL_read(ssl,buf, size);
switch(SSL_get_error(ssl,ret)){
case SSL_ERROR_NONE:
goto read_done; //真正讀完
case SSL_ERROR_ZERO_RETURN:
ret=SSL_shutdown(ssl);
goto end;
case SSL_ERROR_WANT_READ:
read_blocked=1;
break;
default:
DBG("SSL read problem\n");
}
} while (SSL_pending(ssl)&& !read_blocked);
3.5 SSL 的擴展
在ARM這種相對于PC 處理器運算能力弱很多的處理器上,必須選擇安全性高且速度有快的加密算法,RC4 是最理想的選擇,下表為采用SSL_RC4_MD5 加密方式的傳輸與普通TCP 傳輸的一組速率對比:
表 1 TCP 和SSL 傳輸速率測試(處理器:190MHz,以太網:100M)
從表中可以看到隨著傳輸數據量的增大,傳輸率逐步趨于穩定,可以推測出為最大的數據傳輸率,TCP約為5.2MB/S,SSL 約為2.34MB/S。在SSL 下,若以半雙工的方式傳輸,而根據串口固定的波特率,可以以“波特率*N<最大數據傳輸率”的公式求得在此波特率下可支持的串口數,在測試中,以四個串口為例,當四個串口波特率都設為460800bps 時,仍能正常通信。
4 總結
通過對設計目標的需求分析,結合ARM9 及Linux軟硬件平臺豐富資源的優勢整合,設計的串口服務器實現了多用戶多點訪問以及安全通信。為串口設備接入互聯網提供了更好的選擇。
-
嵌入式
+關注
關注
5092文章
19177瀏覽量
307674 -
物聯網
+關注
關注
2913文章
44925瀏覽量
377022 -
Linux
+關注
關注
87文章
11345瀏覽量
210395 -
服務器
+關注
關注
12文章
9304瀏覽量
86062
發布評論請先 登錄
相關推薦
評論