嵌入式系统中网络通信模块的实现
扫描二维码
随时随地手机看文章
0.引言
嵌入式系统由嵌入式微处理器、外围硬件设备、嵌入式操作系统和专用的应用程序组成。嵌入式系统一般是实时控制系统,其关键是嵌入式实时操作系统。VxWorks是Wind River公司开发的一种嵌入式强实时操作系统。它为嵌入式开发提供了高效的实时任务调度、中断管理、实时的任务间通信等。网络是VxWorks系统之间及其与其他系统联系的主要途径,本文讨论了VxWorks网络通信的有关机制,给出了VxWorks网络通信在一个嵌入式系统中的应用实例。
1. VxWorks中的网络通信原理
1.1 VxWorks的网络协议
VxWorks提供了强大的网络功能,能与许多主机系统进行通信。VxWorks实现了与BSD4.4 TCP/IP兼容的网络协议栈,并且加强了实时性。在网络结构最底层,VxWorks通常使用以太网作为传输媒介。在传输媒介上,VxWorks使用TCP/IP和UDP/IP协议作为VxWorks进程与其他主机环境进程之间数据传输的工具。VxWorks的所有网络机制都遵循标准的Internet协议。在以太网协议之上,VxWorks提供了以下几种网络工具:套接字(Socket);远程过程调用(Remote Procedure Calls);远程文件存取(Remote File Access);文件输出(File Export);远程命令执行。
1.2 VxWorks中的Socket接口
本文网络通讯接口是基于套接字(socket)来实现的。利用套接字,无论是单一CPU中的不同进程,还是通过共享内存底板,以太网或任何类型的网络连接的进程都可以实现通信。套接字是与网络节点的UDP或TCP端口捆绑在一起的通信接口。VxWorks实现了标准的BSD流套接字和数据报套接字。socket接口增加了网络通信操作的抽象定义,与文件操作一样,每个打开的socket都对应一个整数,称之为socket描述符,它是socket描述符在文件描述符表中的索引值,指向一个与该socket有关的数据结构。
1.3客户/服务器编程模式
网络编程一般采用客户/服务器(Client/Server)模式。服务器端有一个或多个任务在指定的端口等待来自客户端的连接请求,一旦连接成功,即可按约定的数据交换方法和格式进行数据传输。客户端则在需要的时刻向服务端发送连接请求。在C/S编程模式下,网络应用程序可分为客户端程序和服务器端程序。
客户端程序是指发出用户请求的程序,它需要知道服务端的地址,提供服务的端口号,服务所用的传输层协议类型。服务器端程序是提供服务的一方,它侦听某个端口,等待来自客户端的请求消息。在程序结构上,服务端程序可使用循环模式和并发模式。循环模式是指程序结构总体上是一个循环,一次处理一个请求。并发模式是指服务端程序可同时处理多个请求,结构上一般采用父进程接受请求,然后产生子进程来处理请求。并发模式设计时也可采用单进程的结构,即使用select调用来获得异步I/O。
2.基于socket的C/S编程模式的嵌入式系统应用实例
2.1嵌入式系统的结构
本嵌入式系统作为一个整机系统的子系统运行于VME总线的VME处理器上。用户通过访问板卡驱动来控制硬件板卡,板卡驱动与硬件板卡通过VME总线完成通信。系统结构意图如图1所示。
500)this.style.width=500;" border="0" />
图1:板卡驱动程序示意图
硬件板卡主要由DSP子系统组成,它接收外部传感器信息,控制执行器实现目标功能。DpRAM模块是VME处理器和硬件板卡之间共享的双端口RAM。板卡驱动程序的目的是提供一系列接口函数,对用户屏蔽掉硬件板卡的硬件细节。其主要任务是分发硬件板卡命令,传递命令伴随的I/O参数。板卡驱动程序运行于VME总线的实时操作系统VxWorks上。
2.2网络中间件
根据上面介绍的VxWorks中的网络通信原理,我们开发了一个用于分布式系统上的任务/进程之间的通信模块CX(Communication eXchange)。本文中CX公共模块采用的是基于TCP协议的流套接字和阻塞模式,其中TCP协议是一种面向连接的通信方式,提供了有序的、无重复并且无记录边界的数据流服务,同时流量和拥塞控制以及传输数据校验保证了数据传输质量;阻塞模式节约资源,仅当客户与服务端连接时才占用计算机芯片处理时间。[!--empirenews.page--]
系统中CX的作用类似于网络中间件,它将VxWorks中socket编程接口封装成进程间通信的统一接口,从而屏蔽掉底层的通信细节,调用者不需要具备socket通信的技能就能直接调用CX接口函数进行通信。在实际整机系统中,许多不同任务驻留在不同的CPU处理器上,即使同一处理器上由于任务的进一步划分,子任务之间也存在进程之间的通讯。不管通信的实体(任务/进程)在同一CPU上,还是不同CPU上,都能够直接以逻辑地址(CX Address) 利用CX公共通讯模块来进行通信,方便实现了整机系统多点互联的通讯机制。CX模块主要提供了如表1的功能:
500)this.style.width=500;" border="0" />
本文中CX公共模块在设计过程中对以下各方面也进行了兼顾:
1、CX传送数据的实时性保证:网络中间件针对所有接收函数都提供有timeout的功能,这样既避免了client挂起而接收不到回应消息;又使得server端在接收请求消息并等待的同时可进行一些周期性任务的处理;
2、CX的重发机制:当一个server没有侦听到请求时,client可以多次向server重发请求,重发间隔时间由调用者自己设定;
3、CX支持阻塞模式:使用select机制来同步多路I/O复用。允许client从多个server等待回应。server同样也可以使用这样的机制来等待请求消息,或从其它server处等待回应消息;
4、CX的监视机制:提供单独的进程来监视host的状态,一旦某个host不可访问就会产生错误或警告信息。
2.3网络中间件的实例
int CXc_send(const CX_serv serv_addr, const void *msg, int len, int retry_interval )
{
int serv_num;
int result;
//检查调用CX的任务是否已向CX注册,CX是否在本地host上初始化
if((!CX_TaskInitialized)||(!CXs_CXisInitialized()))
{ result = CX_NOT_INITIALIZED; }
//参数检查
else if((len <= 0)||(len>CX_MaxMsgSize))
{ result = CX_ILLEGAL_MSG_LEN; }
else
{ //将server地址转换为server号
result=ServAddr2Num(serv_addr, &serv_num );
if(result == OK)
{ //发送请求消息
result = CXclient_send( serv_num, msg, len, retry_interval );
}
}
return result;
}
int CXclient_send( int serv_num, const void *msg, int len, int retry_interval )
{
int result;
result = CX_CONN_RESET;
while(result == CX_CONN_RESET)
{
//检查cliet是否还与server保持连接,如果没有则建立连接
if(!CXclient_IsStillConnectedTo(serv_num))
{ result = CXc_Connect(serv_num, retry_interval);
if(result != OK)
{ return result; }
}
//向server发送消息
Result = CXFD_WriteMsg(Client_Admin[serv_num].cl_write_fd, msg, len);
//如果没有发送成功,则返回错误码,并修改client相应的项目
if(result == CX_CONN_RESET)
{ Client_Admin[serv_num].cl_is_connected = FALSE; }
}
return result;
}[!--empirenews.page--]
2.4基于网络中间件的板卡驱动程序
板卡驱动的软件结构采用C/S(Client/Server)模式,客户端和服务器通过CX模块通信。Client发送请求消息到指定的server,server从client接收请求消息,执行请求的动作,发送一个包含请求动作执行结果的消息给发送请求的client。消息的内容和解释则全由clients和servers来完成。板卡驱动的软件结构示意图如图2所示。
500)this.style.width=500;" border="0" />
图2:板卡驱动软件结构示意图
板卡驱动的外部接口函数ILDXA_xxx以库文件的形式提供给用户,作为请求服务的客户端。用户通过调用这些接口函数向服务器端发送请求。其中,发送请求消息的函数接口是:CXc_send(const CX_serv serv_addr, const void *msg, int len, int retry_interval)。这里每个server的地址serv_addr与逻辑主机相关,在server地址列表中给出。
请求发送成功后,客户端调用接收返回消息的函数来接收服务端返回消息:CXc_recv(const CX_serv serv addr, void *msg, int len, int *act_len, int timeout)。
服务器端则通过一个无限循环的进程等待来自客户的请求消息,接收请求消息的接口函数是:CXs_recv(const CX_serv serv_addr, void *msg, int len, int *act_len, CX_repl *repl_addr, int timeout)。这里返回地址repl_addr由CX动态分配:当server接收到一个请求消息,CX提供回复消息应该发送的返回地址。
服务器端接收到请求消息后调用相应的处理函数来处理传递过来的命令和参数,并继续等待下一个请求。当命令执行完后,外部中断信号会中断服务器端处理器。中断服务程序ILDISR_command释放信号量来同步服务器端的循环执行的任务。此任务向客户返回一个消息,接口函数:CXs_send(CXXA_repl repl_addr, const void *msg, int len)。
3结束语
VxWorks是一种高效的多任务的嵌入式实时操作系统,网络是VxWorks系统之间以及与其他系统通信的主要方式。本文讨论了VxWorks中网络通信的关键技术,其创新点在于:利用这种基于socket的面向连接的网络通信机制,开发了普适于整机系统通讯的公共模块-CX网络中间件,具体到该嵌入式分系统应用中实现了上位机与硬件板卡的实时通信,取得了良好的效果。