物联网的出现及迅猛发展为世界经济带来了新的增长点,将那些传统的仪器设备采用统一的方式接入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软硬件平台丰富资源的优势整合,设计的串口服务器实现了多用户多点访问以及安全通信。为串口设备接入互联网提供了更好的选择。
-
嵌入式
+关注
关注
5059文章
18972浏览量
301920 -
物联网
+关注
关注
2900文章
44052浏览量
370086 -
Linux
+关注
关注
87文章
11204浏览量
208701 -
服务器
+关注
关注
12文章
8954浏览量
85069
发布评论请先 登录
相关推荐
评论