工控网首页
>

应用设计

>

嵌入式实时系统中跨平台通信的实现

嵌入式实时系统中跨平台通信的实现

2005/3/25 9:25:00
摘 要: 本文以套接字Socket为基础,提出并设计了一种跨平台嵌入式实时系统的通信模型,并根据这种模型给出了示范。 关键词: 跨平台;嵌入式实时系统;套接字 引言 当前嵌入式系统正以前所未有的速度发展,并广泛应用到通信、军事、航空、航天、工业控制等高精尖技术及实时性要求极高的领域中。在这些领域中,迫切需要一个能够让日益增多的嵌入式设备相互通信的解决方案。同时,由于嵌入式系统的专用性强,在不同领域的嵌入式设备往往使用不同的嵌入式实时操作系统。这样就为构建一个统一的通信平台带来了困难。本文介绍一个不同平台下的嵌入式系统的通信实现方案。 设计目标 灵巧性 完备的嵌入式系统大都具备嵌入式实时操作系统,绝大多数实时操作系统都带有网络协议栈,利用网络协议就可以构建通信平台。TCP/IP协议簇是目前使用最广泛的一种网络通信协议。当前,基于TCP/IP的流行应用,存在功能单一、消耗系统资源等问题。而嵌入式设备一般通信量不大,同时系统资源有限,不能支持大型的应用。所以,嵌入式设备间的通信应当实现简单、可灵活增减。 实时性 实时系统要求系统能够在规定的时间内对外部事件给予响应。但在不同应用中,通信的嵌入式设备间的物理距离不同,使用的通信方式也不尽相同。通信延迟是影响实时系统的主要因素之一。在近距离通信中,可以采用高速通信线路,但是在远距离通信中,则通信线路的选择余地较小。在低速通信线路中,为了提高系统的实时性能,嵌入式实时系统的通信需要设计成多线程多任务,确保每个通信请求都有单独的线程来处理,这样可以保证系统对通信的及时响应。 稳定性 嵌入式实时系统大都具备繁重的测量和运算任务。嵌入式实时系统同时运行大量任务,不能保证系统永不出现问题,但通信任务不能受嵌入式设备本身任务的影响。因此,在设计中,需要把通信任务和实际的检测控制任务分离。用一个专门的任务处理通信事件,同时设立一个缓冲区保证通信数据能够被及时保存。 通用性 嵌入式实时操作系统种类繁多,目前尚无一种操作系统在嵌入式领域占绝对优势。嵌入式设备的跨平台通信必须能够适用于各种常见的实时操作系统,能将不同实时操作系统的嵌入式设备联网。 实现方案 根据嵌入式实时系统不同平台通信的特点,可以采用如下方案设计: 跨平台通信 通信部分采用大多数实时操作系统都支持的TCP/IP协议簇作为系统的基本协议。为了方便使用,采用基于TCP/IP的套接字。套接字是一种仿照电话系统设计,并在UNIX上得到成功应用的进程通信机制,它提供进程间通信的端点。通信之前,进程双方都创建一个端点,服务器端绑定一个固定的端口,客户端则可以随机的申请一个端口。客户可以通过网络向服务器的端口发送连接请求,服务器端接收到请求后允许客户端的连接。这样,服务器端和客户端就建立了一个双向的通信通道。 套接字分为三种类型:流套接字、数据包套接字、原始套接字。流套接字可以提供可靠的、面向连接的通信流,有固定的发送和接收顺序,采用TCP和IP协议。数据包套接字是一种无连接的数据服务,数据通过相互独立的报文进行无序传输,使用UDP和IP协议,它允许对底层协议如IP或ICMP直接访问。原始套接字虽然功能强大,但是使用较复杂,主要用于一些协议的开发和测试工作。 通信处理程序设计成多线程方式。一旦其它嵌入式设备发起连接就启动一个线程或任务专门处理对外部嵌入式设备发送过来的数据,通过解析确定数据的类别并转入相应的处理函数。处理函数的多少可以根据实际应用确定,这样可以最大限度地利用有限的系统资源。 通信数据处理 利用命名管道或共享内存技术,建立一个介于嵌入式设备实际任务和通信处理任务间的缓冲区。 如果通信中嵌入式设备需要连续数据交换,可以使用管道技术。命名管道支持单向和双向进程或任务间的通信。命名管道有两种实现方式:字节模式和消息模式。在字节模式中,消息以一个连续的字节流的形式,在客户机与服务器之间流动。这意味着,对进程双方来说,在任何一个特定的时间段内,它们不能准确知道有多少字节从管道中读入或者写入管道。在消息模式中,客户机和服务器则通过一系列不连续的数据单位,进行数据的收发。每次在管道上发出了一条消息后,它必须作为一条完整的消息读入。因此,消息模式比较适合通信任务和实时任务的数据交换。 如果通信中嵌入式设备只要瞬时数据交换,则可以采用共享内存方式构造缓冲区。简单说地共享内存就是被多个进程共享的内存。共享内存方式是进程间通信方法中最快的一种,它可以将信息直接映射到内存中,省去了许多中间步骤。利用共享内存方式实现进程通信,需要注意进程间的同步问题。如果通信量不大的话,最简单的方法就是对进程双方给予不同权限(读或写),这样就可以省去复杂的同步机制。通信方案的结构框图如图1所示,嵌入式设备间的通信流程如图2所示。
图1 通信方案的结构框图
图2 嵌入式设备的通信流程 部分代码示例 下面给出在两个常见的嵌入式设备操作系统下通信的实现代码: 主动通信方代码 主动通信方选择WinCE为操作系统。WinCE与Windows2000都是使用WinSocket,因此编程方法基本相同。 #include "Winsock2.h" #include "Windows.h" WSADATA wsaData;//使用的WinSocket版本 //使用的通信协议标志 struct protoent *ppe; //待通信Socket的地址 struct sockaddr_in daddr; //读写数据长度 DWORD cbRead=0,cbWritten=0; BOOL fSuccess=false;//通信标志 //通信程序 DWORD HostConnect(void) { //确定使用WinSocket的版本 WSAStartup(MAKEWORD (2,2),&wsaData ); //创建一个基于TCP的套接字 ppe=getprotobyname("tcp"); SOCKETClientSocket=socket (PF_INET,SOCK_STREAM,ppe->p_proto); //连接一个套接字 //使用TCP协议 daddr.sin_family=AF_INET; //设定待连接的端口 daddr.sin_port=htons(TargetPort); daddr.sin_addr.s_addr=inet_addr (TargetIPAddress);//设定待连接设备的IP地址 //连接目的嵌入式设备 if(connect(ClientSocket,(struct sockaddr *)&daddr,sizeof(daddr))) {closesocket(ClientSocket);} else { //发送消息 ......//准备发送的数据 cbWritten=send(ClientSocket,SData,strlen(SD ata)),MSG_DONTROUTE); //接收消息 do { cbRead=recv(ClientSocket,RData,50,MSG_PEEK); if(cbRead>0) {fSuccess=true;} }while(!fSuccess); ...... //数据处理 //关闭Socket closesocket(ClientSocket) } return(0); } 被动通信方代码 被动通信方选择VxWorks为操作系统。Linux与VxWorks都可以使用BSD Socket,因此编程方法基本相同。通信任务和实时任务的数据交换以管道方式为例。 #include "vxWorks.h" #include "sockLib.h" #include "inetLib.h" #include "taskLib.h" //本机Socket地址 struct sockaddr_in serverAddr; //目标通信机Socket地址 struct sockaddr_in clientAddr; int sFd; //监听Socket描述苻 int newFd; //被连接Socket描述苻 int ix=0;//被连接的Socket数目 //启动管道函数 void SetupPipe(void) { pipeDrv();//管道驱动 //管道建立 pipeDevCreate(“\pipe\ mypipe”,20,40); } //主通信函数 void Server(void) { //使用TCP/IP协议 serverAddr.sin_family = AF_INET; serverAddr.sin_len = sizeof (struct sockaddr_in); //本机提供通信的端口 serverAddr.sin_port = htons(HostPort); serverAddr.sin_addr.s_addr = htonl (HostIP);//本机IP地址 //创建Socket sFd = socket (AF_INET, SOCK_STREAM, 0); //绑定Socket bind (sFd, (struct sockaddr *) &serverAddr, sockAddrSize); //监听Socket listen (sFd, SERVER_MAX_CONNECTIONS); //等待通信事件发生 FOREVER { newFd = accept (sFd, (struct sockaddr *) &clientAddr,&sockAddrSize); sprintf (workName, "tTcpWork%d", ix++); taskSpawn(workName, NORMAL_PRIORITY, 0, NORMAL_STACK_SIZE,(FUNCPTR) tcpCommunicateTask, newFd,(int) 0, 0,0, 0, 0, 0, 0, 0, 0); } } //已连接的通信的处理函数 void tcpCommunicateTask(int sFd,) { do { //读取数据 ReadBytes=recv(sFd,chRequest, sizeof(chRequest),MSG_PEEK); if(ReadBytes == 0) break; else RSuccess=true; GetAnswerToRequest(chRequest, chReply,&ReplyBytes);//数据处理 //返回数据 WriteBytes = send (sFd, chReply, ReplyBytes ,MSG_DONTROUTE); if ( WriteBytes!= ReplyBytes) break; else WSuccess=true; }while(!(RSuccess && WSuccess)); //关闭Socket close (sFd); } //处理数据函数 void GetAnswerToRequest(char * Request, char * Reply, int * ReplyBytes) { //打开管道(每个任务有不同的管道) int fd=open("\pipe\mypipe", O_RDWR,0); ......//相应的数据交换 } 结语 使用这种嵌入式实时系统的跨平台通信方案,不但可以实现嵌入式设备异平台的互联互
投诉建议

提交

查看更多评论
其他资讯

查看更多

蓝牙技术的安全机制

步进电机的控制原理及其单片机控制实现

基于USB总线和89C51单片机的数据采集系统设计