Tornado和VxWorks学习笔记.docx
- 文档编号:8520876
- 上传时间:2023-01-31
- 格式:DOCX
- 页数:15
- 大小:28.50KB
Tornado和VxWorks学习笔记.docx
《Tornado和VxWorks学习笔记.docx》由会员分享,可在线阅读,更多相关《Tornado和VxWorks学习笔记.docx(15页珍藏版)》请在冰豆网上搜索。
Tornado和VxWorks学习笔记
TornadoandvxWorks学习笔记-myc
环境配置相关:
1.tornado2.2在启动时,弹出一个警告窗口如下:
Warning:
CannotfindavalidTornadoRegistryonhost"".
YouneedtohaveaccesstoaTornadoRegistrytoconnecttoanytargets.ForinstructionsonhowtostarttheTornadoRegistry,pleaserefertothedocumentation.
应该如何解决?
解决方法:
启动Tornado后,选择TooloptionsTornadoRegistry勾选Localregistry。
问题原因:
TornadoRegistry即Tornado目标服务器注册表,这种注册表可以使主机通过名称连接目标服务器(运行主机工具的主机和运行目标服务器的机器可以不同)。
也即说,这个注册表必须一致处于运行状态,否则主机工具就不能联系上运行目标服务器的机器,也就不能与目标机进行通信。
而由于我们的机器同时运行主机工具和目标服务器,因此,我们只需要将TornadoRegistry建立为本地的就可以了。
所以,要勾选Localregistry。
(由于Tornado工具与目标机通信的方式无关,所以无论与目标机的通信方式是通过网络还是通过串口,注册表都是必须的。
)
2.目标机代理执行的模式有三种:
1任务模式:
目标机代理作为VxWorks的一个任务,用户可以再不影响目标系统运行的情况下隔离某个任务。
2系统模式
3双模式
3.TornadoLaunch工具条是一个下拉列表,显示了当前运行的并注册过的目标服务器。
如果没有目标服务器列出,或没有用户需要的目标服务器,则用户必须配置和启动一个目标服务器。
4.目标服务器管理Tornado主机工具和VxWorks目标机代理间的通信。
在主机工具与目标机交互前,必须针对该目标机配置并启动目标服务器。
5.在Tornado内建立一个开发环境,具体步骤如下:
1设好目标机硬件
2定义主机环境变量,配置好网络软件;在\x86-win32\bin下,有torwars.bat脚本程序,用来设置环境变量;网络要配置好TCP/IP协议,修改主机host文件。
3开启Tornado目标服务器注册表。
4指明目标机启动参数(bootparameters),并启动目标机。
(最开始学习的时候,没有目标机的话,就用VxSim吧)
5配置并启动目标服务器(targetsever),目标服务器是管理主机开发工具和目标机通讯的。
6.VxWorks具有可移植性的原因是采用了模块化的设计,它将所有硬件的功能函数分别放到一系列库中,这些库就称之为板级支持包BSP(BoardsupportPackage)。
7.BSP库为实现所有目标板上各种硬件的功能提供了相同的软件接口,包括如下功能:
1硬件初始化
2中断的产生与处理
3硬件时钟和定时器管理
4本地及总线存储空间映射
5设置存储空间大小
6等等
8.*在一块新的目标板上安装VxWorks操作系统是很困难滴,是因为我们不能无法使用VxWorks的开发工具,并且,也没有相对应的BSP。
但是,Tornado软件为我们提供了VxWorks的BSP开发工具包,这个BSP的开发工具包提供的一些策略可以使VxWorks的安装变得容易点。
(BSP工具包的用户应该具备低级c语言和汇编语言的编程经验,熟悉设备驱动程序,熟悉中断处理程序以及软硬件之间的接口)
BSP工具包包含一套文献资料和一些软件。
其中,文献资料包括:
①安装指南②用户手册
软件包括:
1BSP合法性测试包
2BSP模板
3驱动程序模板
4SCSI测试包(SCSI:
smallcomputersysteminterface,小型计算机系统接口)
9.在运行具有网络功能的vxsimfullsimulator的时候,如果在启动targetServer时遇到如下错误:
Error:
rpccorebackendclientTimedoutfailed.
则需要检查以下几点:
1)检查ULIP虚拟网络适配器的ip地址是否配置为:
192.168.255.254
2)VxWorks组件中,developmenttoolcomponents/WDBagentcomponents/selectWDBconnection/中,应当仅选择WDBENDdriverconnection选项.
同时,selectWDBmode应当仅选择WDBtaskdebugging选项.
3)TargetServer的配置里面,TargetServerProperties应当选择BackEnd(表示通过网口调试),AvailableBack处应选择wdbrpc选项.
TargetName/IpAddress可以填目标机地址.例如:
192.168.255.1
(还有一次,直接targetserver都打不开,之前一直好好的,忽然间就出错了,一直遇到这种错误:
error:
simulatorfailedtoinitializebeforetimeout
我是这么解决的:
先新建了一个project,然后重新编译了一个最原始的vxworks.exe,然后打开.
再之后又重新开之前的那个vxworks.exe然后居然就正常了)
10.如果想要能够有ping功能,需要包含组件networkconmponents/networkingprotocols/networkapplications/PINGclient.
11.如果vxsim0和vxsim1不能互相ping通,但vxsim0和vxsim1可以ping通主机,则说明组件:
networkconmponents/networkingprotocols/coreTCP/IPconmponents/ICMPv4没有被包含进去.
12.Simulator与其它主机的通信
假设host0(你的主机,simulator运行于此机上)的Ip为10.12.9.113,host1的Ip为10.12.9.129.如果host1想与simulator通讯,只需在host1的路由表中增加一项:
Routeadd192.168.255.110.12.9.113metric1
然后可以分别在host1上ping192.168.255.1和simulator上ping10.12.9.129进行验证.
网络编程相关:
Tcp(基于连接的)编程
1.相关概念:
端口:
RFC1700规定常用的端口号从0-1023,1024-49151是已注册的端口号.
这个端口号很重要,比如在客户机/服务器模型下,服务器端有一个任务在指定的端口等待客户来连接(在vxworks当中,是先通过listen函数监听端口,然后accept函数接受来自client端的连接来实现的),一旦连接上之后,就可以按设计的数据交换方法和格式进行数据传送.
2.客户机/服务器通信过程:
对server来说,包括如下几个步骤(注意:
结构体structsockaddr_in和structsockaddr是不一样滴两个结构):
1)创建一个tcpsocket.
eg:
intsd=socket(AF_INET,SOCK_STREAM,0);/*其中,sd是socket描述符,由socket函数返回.AF_INET得看Help文件具体才知道是什么意思,反正大多都用这个.SOCK_STREAM说明是建立的一个基于连接的socket,也即tcpsocket.*/
2)分配一个server的端口给第1步中创建的socket.也即让创建的那个socket和某个端口绑定起来,否则server到哪监听想要连过来的client呢?
绑定了之后相当于server就在这个端口这里等待client的连接请求了.
VxWorks下面,是通过bind函数绑定socket和分配的端口的,如下:
bind(sd,(structsockaddr*)&serverAddr,sizeof(structsockaddr_in))
这里的sd即是刚才的建立的socket,可是端口号在哪里呢?
端口号是在serverAddr里面的一个成员里面存着的.serverAddr是structsockaddr_in类型的结构体.其中:
serverAddr.sin_family=AF_INET;/*这个AF_INET我也不明白是何意*/
serverAddr.sin_port=htons(SERVER_NUM);/*SERVER_NUM即为分配的端口号,例如6000(随便自己分一个,大于1023就ok了),htons是将主机字节序转换成网络字节序的意思,因为端口号存在这个结构体当中规定是要存网络字节序滴!
所以这里要转换一下*/
这个结构体里还有其它两个变量,一个是长度(暂时不知道是什么意思,反正不填也没事).还有一个是serverAddr.sin_addr.s_addr是用来存放server的ip地址的(经转换过的长整形ip地址),这个地址在server上面也没什么用,可以不填,因为运行在server上的程序不必要还知道自己的ip地址,但在client上运行的程序代码中,这个地址就需要填了,因为client需要通过server的ip地址来找寻建立socket连接的目标,没有serverip地址,client就不知道该去找谁通信了
3)经过上面两步,socket和端口就绑定起来了.我是这么理解滴:
第1步建立一个tcpsocket,就相当于找了一截水管,端口号就相当于server上一个固定的洞口,把socket和端口号绑定,就相当于是把这截水管的一段连住那个洞口了.连住之后,就等待监听水管的另一头有没有人(client)把它也用个另一根管子接起来.
监听(listen函数):
Listen(sd,4);/*可以理解为server这时在这里等着,看看这个socket和端口结合体有没有client愿意伸跟水管和它连通,4表示等待排列的最大连接数*/
4)接受(accept函数):
当server在listen的时候,发现有个client想要和自己连接(即发现有个client也伸了一根水管想要和自己的水管接起来),这个时候server就做出处理,可以连接.于是,accept函数就把server自己伸出去的水管和client伸过来的水管给连起来了.同时,还把client的一些相关信息给带了回来,保存在结构clientAddr和返回值clientsd里了.如下:
clientsd=accept(sd,(structsockadd*)&clientAddr,&clientLen);/*其中,clientsd即表示client伸过来的socket描述符.Client的ip地址被保存在了clientAddr.sin_addr中*/
当然了,这里的clientLen最开始初始化的时候,应该初始化为sizeof(structsockaddr_in),也即clientAddr的大小,否则accept就得不到client的ip地址了(这是个很恶心的问题,但是必须初始化一下,具体为啥不知道,得看help)
5)水管都接好了,那就通信(”放水,接水”)吧,如下:
recBytes=recv(clientsd,receiveMessage,sizeof(receiveMessage),0);/*从clientsd里面接受数据,数据存放在receiveMessage这个buffer里面*/
对client来说,就包括下面几个步骤:
1)建立一个Tcpsocket.
2)把这个socket和server连接起来
注意:
这里说把socket和server连接起来,并不是说把socket和server的socket连接起来.因为client又没有监听机制,并不知道server的socket是多少.对于client来说,知道的仅仅是server的ip地址以及分配的端口号(其实端口号就对应一种服务,例如常用的端口号telnet(23),ftp(21),smtp(25),http(80)都是分配好的.如果你想写一个telnet的client程序,那么你就知道要用server的23号端口来进行通信).
连接的方法如下:
connect(sd,(structsockaddr*)&serverAddr,sizeof(serverAddr));
(注意:
这里的serverAddr在初始化的时候,一定一定一定要记得bzero一下,否则connect的时候打死的连不上.)
其中,sd是client的socket,serverAddr.sin_family一般填AF_INET,serverAddr.sin_port就需要填写服务对应的端口号,serverAddr.sin_addr.s_addr需要填写server端的ip地址(vxworks中需要用inet_addr函数将其转换成长整形的ip地址)
当client端发出connect请求,如果此时server段空闲,并accept了这个connet请求,那么就可以进行通信了.
3)通信:
send(sd,sendMessage,sizeof(sendMessage),0);/*发送数据,sendMessage即为需要发送的数据*/
udp(基于非连接的)编程
1.通信进程
对于server来说,步骤如下:
1)建立socket(同tcp一样)
2)绑定端口(同tcp一样)
3)接受数据.
Udp通信由于不是面向连接的通信,提供的是不可靠服务,因此不需要建立连接.直接可以接收数据.Vxworks下面是通过recvfrom来实现.如下:
recvfrom(sd,receiveMessage,sizeof(receiveMessage),0,(structsockaddr_in*)&clientAddr,&clientLen);
/*其中,sd为socket,receiveMessage为一个保存接收数据的buffer,clientAddr在函数返回的时候(也即接收到数据的时候)会将发送数据端的地址保存下来,clientLen为保存clientAddr长度的一个变量,需要注意的是:
这个clientLen在recvfrom函数调用之前必须初始化为sizeof(structsockaddr_in),否则得不到发送端的地址!
这一点很恶心,具体原因需见help*/
4)根据需要,回复发送端.(如果不需要通知发送端数据已收到,这步也可省略)
sendto(sd,responseMeg,sizeof(responseMeg),0,(structsockaddr*)&clientAddr,clientLen);
/*其中,responseMeg是回复的内容,clientAddr即是通过recvfrom函数得到的发送端地址.*/
对于client来说,步骤如下:
1)建立socket
2)发送数据
sendto(sd,sendMessage,sizeof(sendMessage),0,(structsockaddr*)&serverAddr,sizeof(serverAddr));
/*其中serverAddr需要填的内容有sever端地址和端口号,sendMessage为要发送的内容.*/
此处不需要绑定端口,直接即可通过socket发送数据.
3)如果需要接受server端的回复,可通过recvfrom函数接收消息.
MUX编程
1.相关概念.
END驱动与MUX接口概述
VxWorks下增强型网络驱动-END(EnhancedNetworkDriver)是一个数据链路层驱动程序,增强型网络驱动(END)是OSI模型中数据链路层的实现,通过MUX函数与网络协议层通讯.END驱动程序是基于MUX模式,网络驱动程序被划分为协议组件和硬件组件.MUX作为数据链路层和网络层之间的接口,它管理网络协议接口和低层硬件接口之间的交互,将硬件从网络协议的细节中隔离出来;删除使用输入钩例程来过滤接收从协议来的数据包,和删除了使用输出钩例程来过滤协议包的发送;并且链路层上的驱动程序需要访问网络层(IP或其他协议)时,也会调用相关的MUX例程.值得注意的是,网络层协议和数据链路层驱动程序不能直接通讯,它们必须通过MUX.MUX的目的是提供一个接口,隔离网络接口驱动和网络服务,MUX支持两种网络驱动接口类型:
–END:
EnhancedNetworkDriver,一种面向帧结构的驱动.
–NPT:
NetworkProtocolToolkit,一种面向分组的驱动,所有链路层信息被去除.
个人理解,以交换机为例.一个交换机的接口就是一个enddriver,物理层的信息暂时就不管了,我们在编程时看到的是链路层.也就是说,这个enddriver在接受\发送数据包时都是以帧为单位的(比如说0x00,0x04,0x67,0x00,0x00,0x01,……).假如现在要编写一个处理包的协议,需要对帧进行处理,那么在编写协议代码的时候,需要通过mux来将end接口收到的包送到指定的处理函数里面.同时,需要发送包的时候,将编辑或处理过的包通过mux送到end接口,然后让end接口发送出去.
因此,mux是连接enddriver和协议之间的接口,编写协议的人员即可以不用去理会driver的具体实现过程,通过mux,可以实现协议的灵活裁剪.
网络协议是OSI模型中网络层和传输层的实现.在基于END驱动vxWorks中,网络协议通过MUX接口与数据链路层进行通信,所有与具体网络接口相关的事务都在数据链路层驱动中进行处理,如发送和接收数据等.
2.muxBind函数
void*muxBind
(
char*pName,/*interfacename,forexample,ln,ei,...*/
intunit,/*unitnumber*/
BOOL(*stackRcvRtn)(void*,long,M_BLK_ID,LL_HDR_INFO*,void*),/*receivefunctiontobecalled.*/
STATUS(*stackShutdownRtn)(void*,void*),/*routinetocalltoshutdownthestack*/
STATUS(*stackTxRestartRtn)(void*,void*),/*routinetotellthestackitcantransmit*/
void(*stackErrorRtn)(END_OBJ*,END_ERR*,void*),/*routinetocallonanerror.*/
longtype,/*protocoltypefromRFC1700andmany*/
/*othersources(forexample,0x800isIP)*/
char*pProtoName,/*stringnameforprotocol*/
void*pSpare/*perprotocolsparepointer*/
)
Forexample:
muxBindCookie=muxBind(ifName,unit,StackRecvRtn,StackShutdownRtn,StackTxRestartRtn,StackErrorRtn,MYOWN_PROTO,pProtoName,pSpare);
参数:
ifName:
enddriver也即一个物理接口的名称.
unit:
enddriver的编号.
StackRecvRtn:
用户自定义的用来处理接受到的包的函数,函数原型为:
STATUSStackRecvRtn(void*pCookie,longtype,M_BLK_IDpMblk,LL_HDR_INFO*pLinkHdr,void*pSapre);
StackShutdownRtn:
关闭处理函数.
StackTxRestartRtn:
重启处理函数.
StackErrorRtn:
出错处理函数.
MYOWN_PROTO:
自己定义的一个协议类型,如#defineMYOWN_PROTO0xfff9
pProtoName:
协议名称.
pSpare:
协议的备用指针,可以用来存储一些需要的数据结构,在muxBind之后,该指针会传入到StackRecvRtn函数中去.
muxBindCookie:
为muxBind的函数返回值指针.这个Cookie记录了协议函数和enddriver之间的相关联信
息.有了这个cookie,即可以方便的知道协议函数是和哪一个enddriver绑定了.这个cookie指向的是一个MUX_BIND_ENTRY结构,当调用完muxBind之后,也即当把用户自定义的包处理函数和enddriver绑定之后,这个结构的就会被填充起来记录相关信息.具体如下:
typedefstructmuxBindEntry
{
intunitNo;/*unit号*/
chardevName[END_NAME_MAX];/*设备名*/
longnetSvcType;/*协议类型,值等于muxBind函数的type值,如0xfff9*/
longnetDrvType;/*networkDrivertype,设备类型*/
UINT32flags;/*BIBentryflags,暂时不知道*/
END_OBJ*pEnd;/*绑定的end信息*/
void*pNetCallbackId;/*和用户传进的pSpare指针指向的内容一样*/
FUNCPTRaddrResFunc;/*referencetoAddressresolutionfunction*/
FUNCPTRnetStackRcvRtn;/*用户定义的那个包处理函数地址*/
}MUX_BIND_ENTRY,*MUX_ID;
包处理函数的介绍:
muxBind函数的
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Tornado VxWorks 学习 笔记
![提示](https://static.bdocx.com/images/bang_tan.gif)