VxWorks操作系统基础.docx
《VxWorks操作系统基础.docx》由会员分享,可在线阅读,更多相关《VxWorks操作系统基础.docx(33页珍藏版)》请在冰豆网上搜索。
![VxWorks操作系统基础.docx](https://file1.bdocx.com/fileroot1/2023-1/8/caa3f4e7-cc6f-4648-956d-76122ad5fd3e/caa3f4e7-cc6f-4648-956d-76122ad5fd3e1.gif)
VxWorks操作系统基础
VxWorks操作系统基础
1实时操作系统概述3
1.1实时操作系统3
1.2基本概念3
2VxWorks的系统综述4
2.1VxWorks4
2.2Tornado6
3VxWorks操作系统基础7
3.1VxWorks的任务7
3.1.1多任务7
3.1.2任务的状态迁移8
3.1.3Wind内核的任务调度9
3.1.4任务控制9
3.1.5任务扩展性12
3.1.6任务错误状态:
errno13
3.1.7任务异常处理14
3.1.8共享代码和代码重入14
3.1.9VxWorks的系统任务17
3.2任务间通信18
3.2.1共享数据结构18
3.2.2互斥18
3.2.3信号量Semaphores19
3.2.3.1二值信号量20
3.2.3.2互斥信号量22
3.2.3.3计数信号量23
3.2.3.4信号量的特殊参数24
3.2.4消息队列24
3.2.5管道26
3.2.6跨网络的任务间通信26
3.2.7信号26
3.3中断服务代码27
3.3.1应用代码与中断连接27
3.3.2中断堆栈28
3.3.3ISRs的一些特殊限制28
3.3.4中断级别的异常28
3.3.5保持高中断级别29
3.3.6对高中断级别的ISRs的一些附加限制29
3.3.7中断与任务间的通信29
3.4看门狗计时器WatchdogTimers29
4VxWorks中的函数库:
30
4.1TaskLib:
30
4.2ErrnoLib:
30
4.3SigLib:
31
4.4LstLib:
31
4.5MemLib:
32
1实时操作系统概述
1.1实时操作系统
在计算的早期开发的操作系统的最原始的结构形式是一个统一的实体(monolithic)。
在这样的系统中,提供的不同功能的模块,如处理器管理、内存管理、输入输出等,通常是独立的。
他们在执行过程中并不考虑其他正在使用中的模块,各个模块都以相同的时间粒度运行,即严格按时间片分时方式运行。
由于现代实时环境需要许多不同的功能,以及在这样的环境中存在的并发活动所引起的异步性和非确定性,操作系统变得更加复杂。
所以早期操作系统的统一结构的组织已经被更加精确的内部结构所淘汰。
层次结构的起点----内核
操作系统的最好的内部结构模型是一个层次性的结构,最低层是内核。
这些层次可以看成为一个倒置的金字塔,每一层都建立在较低层的功能之上。
内核仅包含一个操作系统执行的最重要的低层功能。
正象一个统一结构的操作系统,内核提供了在高层软件与下层硬件之间的抽象层。
然而,内核仅提供了构造操作系统其他部分所需的最小操作集。
对一个实时内核的要求。
一个实时操作系统内核需满足许多特定的实时环境所提出的基本要求,这些包括:
多任务:
由于真实世界的事件的异步性,能够运行许多并发进程或任务是很重要的。
多任务提供了一个较好的对真实世界的匹配,因为它允许对应于许多外部事件的多线程执行。
系统内核分配CPU给这些任务来获得并发性。
抢占调度:
真实世界的事件具有继承的优先级,在分配CPU的时候要注意到这些优先级。
基于优先级的抢占调度,任务都被指定了优先级,在能够执行的任务(没有被挂起或正在等待资源)中,优先级最高的任务被分配CPU资源。
换句话说,当一个高优先级的任务变为可执行态,它会立即抢占当前正在运行的较低优先级的任务。
快速灵活的任务间的通信与同步:
在一个实时系统中,可能有许多任务作为一个应用的一部分执行。
系统必须提供这些任务间的快速且功能强大的通信机制。
内核也要提供为了有效地共享不可抢占的资源或临界区所需的同步、互斥机制。
方便的任务与中断之间的通信:
尽管真实世界的事件通常作为中断方式到来,但为了提供有效的排队、优先化和减少中断延时,我们通常希望在任务级处理相应的工作。
所以需要杂任务级和中断级之间存在通信。
性能边界:
一个实时内核必须提供最坏情况的性能优化,而非针对吞吐量的性能优化。
我们更期望一个系统能够始终以50微妙执行一个函数,而不期望系统平均以10微妙执行该函数,但偶尔会以75微妙执行它。
特殊考虑:
由于对实时内核的要求的增加,必须考虑对内核支持不断增加的复杂功能的要求。
这包括多进程处理,Ada和对更新的、功能更强的处理器结构如RISC的支持。
拥有其它名字的内核
许多商用化的内核支持的功能远强于上面所列的要求。
在这方面,他们不是真正的内核,而更象一个小的统一结构的操作系统。
因为他们包含简单的内存分配、时钟管理、甚至一些输入输出系统调用的功能。
1.2基本概念
任务(TASK):
任务是由计算机所执行的一项活动,它包括一个程序和于这个程序有关的数据、程序状态及计算机资源等。
进程(PROCESS):
在UNIX操作系统里,任务被称作进程。
任务和进程都可以作为调度单位被内核调度执行,但在一些既有任务又有进程的系统里任务和进程是有区别的,主要表现在:
任务可以直接对内层进行寻址,而进程不能,进程只能从其父进程里继承一些特定的属性,而任务却能和父任务在几乎相同的环境下运行。
任务的状态:
包括运行、就绪、挂起、休眠等在内的任务所处的状态。
任务的调度:
负责控制各个任务在各个任务状态之间的转换。
任务的控制块(TCB):
任务控制块用来描述一个任务,每一个任务都与一个TCB相关联。
TCB包括了任务的当前状态、优先级、要等待的事件或资源、任务程序码的起始地址、初始堆栈指针等信息。
此外,TCB还被用来存放任务的“上下文”(CONTEXT)。
任务的同步:
对单个任务而言,同步就是使它能在指定的时间执行,对两个或两个以上的任务,同步是任务间需要协调执行的情况。
消息:
消息机制使用一个被各有关进程共享的消息队列,进程之间经由这个消息队列发送和接收消息,并用来协调(同步)对共享资源的使用的方法。
管道(PIPE):
是一个类似文件的结构,它用于同步读/写操作,使用系统调用PIPE可以产生一个管道并返回两个文件指针,一个用于读管道,一个用于写管道。
中断(Interrupt)和中断处理程序(InterruptServiceRoutine):
中断一般是指硬件中断,它用于通知操作系统特定外部事件的发生,中断响应速度对于实时系统是至关重要的。
可以使用intConnect()函数把特定的ISR与某一中断联系起来。
信号(SIGNAL):
它用来通知一个任务特定事情的发生,并立即调用相应的信号处理函数进行处理,它异步的改变任务的控制流程。
信号与中断类似,每个信号通常需要和特定的信号处理程序绑定起来(调用sigaction()或signal())。
信号通常用于错误或异常处理,用于通知一些硬件中断错误,如:
总线错误、非法指令、浮点异常、被零除等。
它也可以用于进程间通讯。
信号量(semaphore):
很多方面类似一个全局变量,不同的是,对信号量的操作(Creat、Delete、Take、Give)都是特定的原子操作,是不可中断的。
信号量主要用于进程间的同步和对共享资源的互斥访问。
2VxWorks的系统综述
2.1VxWorks
VxWorks是美国WindRiverSystem公司(以下简称风河公司,即WRS公司)推出的一个实时操作系统。
Tornado是WRS公司推出的一套实时操作系统开发环境,类似MicrosoftVisualC,但是提供了更丰富的调试、防真环境和工具。
VxWorks操作系统有以下部件组成:
Ø内核(wind):
Ø多任务调度(采用基于优先级抢占方式,同时支持同优先级任务间的分时间片调度)
Ø任务间的同步
Ø进程间通信机制
Ø中断处理
Ø定时器和内存管理机制
ØI/O系统
VxWorks提供了一个快速灵活的与ANSIC兼容的I/O系统,包括UNIX标准的BasicI/O(creat(),remove(),open(),close(),read(),write(),andioctl().),BufferI/O(fopen(),fclose(),fread(),fwrite(),getc(),putc())以及POSIX标准的异步I/O。
VxWorks包括以下驱动程序:
网络驱动、管道驱动、RAM盘驱动、SCSI驱动、键盘驱动、显示驱动、磁盘驱动、并口驱动等
Ø文件系统
支持四种文件系统:
dosFs,rt11Fs,rawFs和tapeFs
支持在一个单独的VxWorks系统上同时并存几个不同的文件系统。
Ø板级支持包BSP(BoardSupportPackage)
板级支持包向VxWorks操作系统提供了对各种板子的硬件功能操作的统一的软件接口,它是保证VxWorks操作系统可移植性的关键,它包括硬件初始化、中断的产生和处理、硬件时钟和计时器管理、局域和总线内存地址映射、内存分配等等。
每个板级支持包括一个ROM启动(BootROM)或其它启动机制。
Ø网络支持:
它提供了对其它VxWorks系统和TCP/IP网络系统的\"透明\"访问,包括与BSD套接字兼容的编程接口,远程过程调用(RPC),SNMP(可选项),远程文件访问(包括客户端和服务端的NFS机制以及使用RSH,FTP或TFTP的非NFS机制)以及BOOTP和代理ARP、DHCP、DNS、OSPF、RIP。
无论是松耦合的串行线路、标准的以太网连接还是紧耦合的利用共享内存的背板总线,所有的VxWorks网络机制都遵循标准的Internet协议。
Ø系列网络产品:
✓WindNetSNMP
✓WindNetSTREAMS
✓WindNet第三方产品,包括OSI、SS7、ATM、FrameRelay、CORBA、ISDN、X.25、
✓CMIP/GDMO、分布式网络管理等。
这些产品扩展了VxWorks的网络特性,并增强了嵌入式处理器的网络特性
Ø虚拟内存(VxVMI)与共享内存(VxMP)
VxVMI为带有MMU的目标板提供了虚拟内存机制。
VxMP提供了共享信号量,消息队列和在不同处理器之间的共享内存区域。
Ø目标代理(TargetAgent)
目标代理遵循WBD(WindDebug)协议,允许目标机与主机上的Tornado开发工具相连。
在目标代理的缺省设置中,目标代理是以VxWorks的一个任务tWdbTask的形式运行的。
Tornado目标服务器(TargetServer)向目标代理发送调试请求。
调试请求通常决定目标代理对系统中其它任务的控制和处理。
缺省状态下,目标服务器与目标代理通过网络进行通信,但是用户也可以改变通信方式。
Ø实用库
VxWorks提供了一个实用例程的扩展集,包括中断处理、看门狗定时器、消息登录、内存分配、字符扫描、线缓冲和环缓冲管理、链表管理和ANSIC标准。
Ø基于目标机的工具
在Tornado开发系统中,开发工具是驻留在主机上的。
但是也可以根据需要将基于目标机的Shell和装载卸载模块加入VxWorks。
总之,VxWorks的系统结构是一个相当小的微内核的层次结构。
内核仅提供多任务环境、进程间通信和同步功能。
这些功能模块足够支持VxWorks在较高层次所提供的丰富的性能的要求。
2.2Tornado
Tornado组成:
ØTornado一整套交叉开发工具
ØVxWorks实时操作系统
Ø连接目标机与宿主机的通信选项
Tornado所提供的工具:
WindConfig:
:
建立适合用户特性的VxWorks操作系统。
Loader:
具有动态连接的装载器。
CrossWind:
源程序(C或C++以及汇编程序等)的调试工具。
CrossWind结合了图形方式和命令行方式的最大特点。
最普通的调试方式,例如断点设置和程序执行控制可以通过便捷的点击方式实现。
同样,程序显示框和数据侦察窗也提供了一个直接的可视窗口来观察应用程序中最关键的一部分。
Browser:
可观察系统对象(任务、消息队列、信号量等)和存储器使用情况;
Browser汇总了应用进程,内存消耗和一个目标内存的映射。
通过Browser,可观察信号量、消息队列、内存分配、看门狗计时器、堆栈使用情况、目标CPU使用率、对象模块结构和符号表以及每个任务的详细信息。
WindSh:
提供从宿主机到目标机之间的一个命令shell,它可以解释执行内层目标中的几乎所有C语言函数或指令(itcaninterpretandexecutealmostallC-languageexpressions)。
WindView:
系统可视诊断和分析工具。
可观察各任务,中断程序之间的相互作用。
它是在嵌入式系统应用开发期间的可视工具。
VxSim:
快速原型仿真器。
可在硬件设备未完成之前,在宿主机上对应用程序进行仿真分析。
他可以在宿主机上模拟目标机的VxWorks操作系统环境,在许多方面他与目标机上的VxWorks系统能力是一样的,他们的区别主要在于:
在VxSim里,内存Image是作为宿主机(WindowsorUNIX)的一个进程执行,没有与目标硬件的交互,所以不适合于设备驱动的仿真。
StethoScope:
实时数据图形监控器。
收集数据,并将数据以图形方法显示出来。
ObjectCenter:
C++开发环境。
选用的是GNUC++编译器,I/O流库支持C++中的格式化I/O。
Tornado调试模式:
系统模式:
对整个应用系统进行调试,可在系统中设置断点等。
调试中应用系统必须停下来
任务模式(动态调试):
调试是针对系统中某一任务模块进行的,整个系统仍可保留在工作状态。
本文中重点介绍了VxWorks操作系统的多任务内核、任务调度、任务间的通信和中断处理机制等核心内容。
3VxWorks操作系统基础
3.1VxWorks的任务
在VxWorks中,一般的应用被组织成相互独立又相互协作的程序,每一个程序在运行时称作一个任务。
在VxWorks中,任务不仅可以共享和快速访问大部分的系统资源,还保留着充分独立的上下文以实现单独的线程控制。
3.1.1多任务
多任务为应用程序对多个离散的现实事件的控制和反应提供了基本的机制。
VxWorks的实时内核wind提供了一个基本的多任务环境。
内核按照一种调度算法交替运行各个任务,造成一种多个任务并行运行的假象,每一个任务都有自己的任务上下文。
任务上下文是任务每次被调度运行时所能看到的CPU环境和系统资源。
在一次上下文切换中,一个任务的上下文被存在任务控制块(TCB)中。
一个任务的上下文包括:
一个用于执行的线程,即任务的程序计数器
CPU的寄存器和可选择的浮点寄存器
用于动态变量和函数调用的堆栈
对标准的输入、输出、出错的I/O口的分配
延时(休眠)时钟
时间片时钟
内核的控制结构
信号句柄
调试和性能监视参数
在VxWorks中,一个非常重要但并不是任务上下文的一项资源就是存储器地址空间:
所有代码(任务)都在一个单一的公有的地址空间运行,这一点是区别于许多非实时操作系统的(UNIX,Windows)。
3.1.2任务的状态迁移
内核维护系统中的每个任务的当前状态。
状态迁移发生在应用程序调用内核功能服务的时候。
任务被创建以后进入挂起态,需要通过特定的操作使被创建的任务进入就绪态,这一操作执行速度很快,使应用程序能够提前创建任务,并以一种快捷的方式激活该任务。
在VxWorks中,任务有以下几种状态,并在这几种状态中切换。
就绪态(ready)----一个任务当前除了CPU不等待任何资源
阻塞态(pend)----一个任务由于某些资源不可获得而被阻塞
延迟态(delay)----一个任务睡眠一段时间
挂起态(suspend)----主要用于调试的一个辅助状态,挂起只是禁止任务的执行,但没有禁止状态迁移。
因此处于pended-suspended状态的任务仍然可以解阻塞(unblocked),处于delayed-suspended状态的任务仍然可以苏醒(awaken)。
另外还有其他一些辅助状态:
DELAY+S任务被delayed+suspended
PEND+S任务被pended+suspended
PEND+T任务被pendedwithatimeoutvalue
PEND+S+T任务被pendedwithatimeoutvalueandsuspended
State+I这个任务的状态取决于当前的状态再加一个继承的优先级
状态的转换:
readypendedsemTake()/msgQReceive()
readydelayedtaskDelay()
readysuspendedtaskSuspended()
pendedreadysemGive()/msgQSend()
pendedsuspendedtaskSuspend()
delayedreadyexpieddelay
delayedsuspendedtaskSuspend()
suspendedreadytaskResume()/taskActive()
suspendedpendedtaskResume()
suspendeddelayedtaskResume()
3.1.3Wind内核的任务调度
多任务需要一个调度算法分配CPU给就绪的任务。
在VxWorks中默认的调度算法是基于优先级的抢占调度,但应用程序也可以选择使用时间片轮转调度。
任务的调度控制程序有:
调度控制函数
函数描述
kernelTimeSlice()控制轮转调度
taskPrioritySet()改变一个任务的优先级
taskLock()禁止任务的重调度
taskUnlock()允许任务的重调度
优先级式的抢先调度
基于优先级的抢占调度,每个任务被指定一个优先级,内核分配CPU给处于就绪态的优先级最高的任务。
调度采用抢占的方式,是因为当一个优先级高于当前任务的任务变为就绪态时,内核将立即保存当前任务的上文,并切换到高优先级任务的上下文。
VxWorks有从0到255共256个优先级。
在创建的时候任务被指定一个优先级,在任务运行的过程中可以动态地修改优先级以便跟踪真实世界的事件优先级。
外部中断被指定优先于任何任务的优先级,这样能够在任何时候抢占一个任务。
时间片轮转式调度
基于优先级抢占调度可以扩充时间片轮转调度。
时间片轮转调度允许在相同优先级的处于就绪态的任务公平地共享CPU。
没有时间片轮转调度,当有多个任务在同一优先级共享处理器时,一个任务可能独占CPU,不会被阻塞直到被一个更高优先级的任务抢占,而不给同一优先级的其他任务运行的机会。
如果时间片轮转被使能,执行任务的时间计数器在每个时钟滴答递增。
当指定的时间片耗尽,计数器会被清零,该任务被放在同一优先级任务队列的队尾。
加入特定优先级组的新任务被放在该组任务的队尾,并将运行计数器初始化为零。
抢占锁定
Wind的调度器可以显式通过tasklock()和taskUnlock()对一个任务锁定或允许抢占调度。
当一个任务通过调用taskLock()来锁定抢占调度,在任务的运行期间就避免了高优先级的任务的抢占。
但如果该任务阻塞或挂起,内核仍然可以调度其他任务运行,一旦该任务重新运行,它又变成不可抢占的。
注意禁止抢先阻止了任务上下文的切换,但不会锁住中断的处理程序。
抢占锁会影响实时操作系统的性能,所以必须保证锁定时间尽量短。
3.1.4任务控制
在VxWorks中的taskLib可以得到有关任务控制的基本例程。
这些程序提供了任务的创建、控制和信息。
任务的创建和激活
任务创建函数
函数描述
TaskSpawn()创建并激活一个新的任务
TaskInit()初始化一个新的任务
TaskActivate()激活一个已经初始化的任务
taskSpawn()的参数包括新任务的名称(ASCII码串),优先级,选项字,堆栈大小,主程序地址(任务的执行函数地址),和10个可以传递给主程序的起始参数。
taskSpawn()创建新任务的上下文,包括分配堆栈、设定具有指定参数的调用主例程的任务环境,新任务从给定的主例程程序入口处开始执行。
id=taskSpawn(name,priority,option,stacksize,main,arg1,…arg10);
taskSpawn()例程屏蔽了低层次的资源分配、初始化、激活步骤。
初始化、激活功能分别由taskInit()和taskActivate()函数提供,然而,建议只有当需要在分配或激活上进一步控制的时候才使用他们。
任务的名字和IDs
当一个任务建立后,你可以规定一个任意长度的ASCII码字符串作为任务的名称,VxWorks将返回一个任务的ID,这个ID是一个指向任务数据结构的4字节的句柄。
通常,ID=0表示当前任务。
任务名字之间不能冲突,同时为了更好使用Tornado开发环境,任务名也不能和全局变量和全局函数冲突。
为了避免命名的冲突,VxWorks约定使用命名前缀:
应用于目标机的任务前缀为“t”,应用于宿主机的任务前缀为“u”。
如果用户不指定任务的名字(调用taskSpawn()时,name=NULL),系统自动赋予任务一个唯一的名字----tN(N是一个可自动累加的十进制整数)。
任务名字和ID的例程
调用描述
TaskName()通过任务的ID来获得任务的名字
TaskNameTold()通过任务的名字查找任务的ID
TaskIdSelf()获得当前任务的ID
TaskIdVerify()核实一个特定任务的存在
任务选项(TaskOptions)
当创建一个任务时,通过运行一个逻辑或操作运算来确定选择的任务选项,就是taskSpawn()函数的第三个参数。
可供设置的选项如下表所列,注意如果任务需要处理浮点运算,那么必须设置VX_FP_TASK选项。
TaskOptions
选项名值描述
VX_FP_TASK0x8在浮点协处理器上运行
VX_NO_STACK_FILL0x100不用0xEE填充堆栈
VX_PRIVATE_ENV0x80在私有环境中执行任务
VX_UNBREAKABLE0x2本任务禁止断点
建立一个包含浮点操作的任务采用以下调用格式:
tid=taskSpawn(“tMyTask”,90,VX_FP_TASK,200000,myFunc,2387,0,0,0,0,0,0,0,0,0);
任务创建之后可