brondjm基于嵌入式操作系统VxWorks的多任务并发程序设.docx

上传人:b****2 文档编号:723284 上传时间:2023-04-29 格式:DOCX 页数:65 大小:94.73KB
下载 相关 举报
brondjm基于嵌入式操作系统VxWorks的多任务并发程序设.docx_第1页
第1页 / 共65页
brondjm基于嵌入式操作系统VxWorks的多任务并发程序设.docx_第2页
第2页 / 共65页
brondjm基于嵌入式操作系统VxWorks的多任务并发程序设.docx_第3页
第3页 / 共65页
brondjm基于嵌入式操作系统VxWorks的多任务并发程序设.docx_第4页
第4页 / 共65页
brondjm基于嵌入式操作系统VxWorks的多任务并发程序设.docx_第5页
第5页 / 共65页
brondjm基于嵌入式操作系统VxWorks的多任务并发程序设.docx_第6页
第6页 / 共65页
brondjm基于嵌入式操作系统VxWorks的多任务并发程序设.docx_第7页
第7页 / 共65页
brondjm基于嵌入式操作系统VxWorks的多任务并发程序设.docx_第8页
第8页 / 共65页
brondjm基于嵌入式操作系统VxWorks的多任务并发程序设.docx_第9页
第9页 / 共65页
brondjm基于嵌入式操作系统VxWorks的多任务并发程序设.docx_第10页
第10页 / 共65页
brondjm基于嵌入式操作系统VxWorks的多任务并发程序设.docx_第11页
第11页 / 共65页
brondjm基于嵌入式操作系统VxWorks的多任务并发程序设.docx_第12页
第12页 / 共65页
brondjm基于嵌入式操作系统VxWorks的多任务并发程序设.docx_第13页
第13页 / 共65页
brondjm基于嵌入式操作系统VxWorks的多任务并发程序设.docx_第14页
第14页 / 共65页
brondjm基于嵌入式操作系统VxWorks的多任务并发程序设.docx_第15页
第15页 / 共65页
brondjm基于嵌入式操作系统VxWorks的多任务并发程序设.docx_第16页
第16页 / 共65页
brondjm基于嵌入式操作系统VxWorks的多任务并发程序设.docx_第17页
第17页 / 共65页
brondjm基于嵌入式操作系统VxWorks的多任务并发程序设.docx_第18页
第18页 / 共65页
brondjm基于嵌入式操作系统VxWorks的多任务并发程序设.docx_第19页
第19页 / 共65页
brondjm基于嵌入式操作系统VxWorks的多任务并发程序设.docx_第20页
第20页 / 共65页
亲,该文档总共65页,到这儿已超出免费预览范围,如果喜欢就下载吧!
下载资源
资源描述

brondjm基于嵌入式操作系统VxWorks的多任务并发程序设.docx

《brondjm基于嵌入式操作系统VxWorks的多任务并发程序设.docx》由会员分享,可在线阅读,更多相关《brondjm基于嵌入式操作系统VxWorks的多任务并发程序设.docx(65页珍藏版)》请在冰点文库上搜索。

brondjm基于嵌入式操作系统VxWorks的多任务并发程序设.docx

brondjm基于嵌入式操作系统VxWorks的多任务并发程序设

!

_

世界上有两种人,一种人,虚度年华;另一种人,过着有意义的生活。

在第一种人的眼里,生活就是一场睡眠,如果在他看来,是睡在既温暖又柔和的床铺上,那他便十分心满意足了;在第二种人眼里,可以说,生活就是建立功绩……人就在完成这个功绩中享到自己的幸福。

--别林斯基

 

基于嵌入式操作系统VxWorks的多任务并发程序设计

(1)――基本概念

02月13th,2006by宋宝华

作者:

宋宝华e-mail:

21cnbao@出处:

软件报

(转载请务必注明作者与出处)

1引言

嵌入式系统定义为:

嵌入到对象体系中的专用计算机系统。

“嵌入性”、“专用性”与“计算机系统”是嵌入式系统的三个基本要素,对象系统则是指嵌入式系统所嵌入的宿主系统。

目前,随着高端消费类电子产品(如PDA、手机、智能家电)的普及,嵌入式计算机系统获得了相当广泛的应用。

操作系统在嵌入式软件体系中占据着重要低位,学习和掌握相关的知识是一名嵌入式系统研发人员的必须。

1.1本文的读者对象与写作目的

本文针对的读者对象为入门级的嵌入式系统软件开发人员以及其他对嵌入式操作系统感兴趣的朋友,顺利阅读本文需要读者具备的基本知识能力为:

(1)熟练的C语言程序设计能力;

(2)操作系统的基本知识。

如果读者具备在Windows平台下进行多线程程序设计或者其他嵌入式操作系统本台下进行多任务程序设计的经验,将对阅读本文有很大的帮助。

本文虽然以VxWorks为介绍的主体对象,但是其中所论述的概念和方法并不局限于VxWorks操作系统本身。

它们也同样适用于其它嵌入式操作系统,如WinCE、嵌入式Linux、ucos等,所谓“万变不离其宗”。

笔者力求能以通俗和形象的语言进行论述,但是由于水平有限,文中难免存在错误和纰漏,诚盼读者朋友指正。

1.2为什么以VxWorks为写作对象

之所以选择VxWorks操作系统为本文的写作对象,是因为:

(1)VxWorks具备清晰的多任务并发控制及任务间通信的成熟机制;

(2)VxWorks有广泛的使用基础,国内外分布着大量的VxWorks程序员;

(3)VxWorks简单易学,便于我们集中目标讲解多任务控制程序本身。

1.3什么是VxWorks

VxWorks操作系统是美国WindRiver公司于1983年设计开发的一种嵌入式实时操作系统(RTOS),它凭借着良好的可持续发展能力、高性能的内核以及友好的用户开发环境,在嵌入式实时操作系统领域占据了重要一席。

VxWorks具备高可靠性和实时性,因而被广泛地应用在通信、军事、航空、航天等高精尖技术及实时性要求极高的领域中,如卫星通讯、军事演习、弹道制导、飞机导航等。

在美国的F-16、FA-18战斗机、B-2隐形轰炸机和爱国者导弹上,甚至连1997年4月在火星表面登陆的火星探测器上也使用到了VxWorks。

VxWorks的实时性体现在它能在限定时间内执行完规定的功能并对外部的异步事件作出响应。

实时操作系统主要应用于过程控制、数据采集、通信、多媒体信息处理等对时间敏感的场合;而分时操作系统按照相等的时间片调度进程轮流运行,无法实时响应外部异步事件,因而主要应用于科学计算和实时性要求不高的场合。

VxWorks由一个体积很小的内核及一些可以根据需要进行定制的系统模块组成。

VxWorks内核最小为8KB,即便加上其它必要模块,所占用的空间也很小,且不失其实时、多任务的系统特征。

VxWorks的内核主要包括:

(1)多任务:

为满足真实世界事件的异步性,现代操作系统需提供多任务支持,由系统内核分配CPU给多个任务并发执行。

如果是单CPU,则执行方式实质是宏观并行、微观串行;

(2)任务调度:

真实世界的事件具有继承的优先级,当一个高优先级的任务变为可执行态,它会立即抢占当前正在运行的较低优先级的任务,VxWorks对这种优先级抢占调度(PreemptivePriorityScheduling)提供了支持。

同时,VxWorks也支持同优先级任务间的时间片轮转调度(Round-RobinScheduling);

(3)任务间的通讯与同步:

在一个实时系统中,系统必须提供多个任务间快速且功能强大的通信机制,并提供为了有效地共享不可抢占的资源或临界区所需的同步机制;

(4)任务与中断之间的通信:

许多外设以中断方式与CPU通信,我们不宜在中断服务程序(ISR)中进行过多的处理,通常将相应处理交给特定任务去完成。

VxWorks前些年对我国一直采取禁运措施,自从对中国的销售解禁以来,它在中国赢得了越来越多的用户。

2进程、线程与任务

既然我们是讲解一种操作系统,那我们就有必要再老生长叹一次进程与线程的概念及其区别。

进程(Process)是具有一定独立功能的程序关于某个数据集合上的一次运行活动,是系统进行资源分配和调度的一个独立单位。

程序只是一组指令的有序集合,它本身没有任何运行的含义,只是一个静态实体。

而进程则不同,它是程序在某个数据集上的执行,是一个动态实体。

它因创建而产生,因调度而运行,因等待资源或事件而被处于等待状态,因完成任务而被撤消,反映了一个程序在一定的数据集上运行的全部动态过程。

线程(Thread)是进程的一个实体,是CPU调度和分派的基本单位。

线程不能够独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。

线程和进程的关系是:

线程是属于进程的,线程运行在进程空间内,同一进程所产生的线程共享同一内存空间,当进程退出时该进程所产生的线程都会被强制退出并清除。

线程可与属于同一进程的其它线程共享进程所拥有的全部资源,但是其本身基本上不拥有系统资源,只拥有一点在运行中必不可少的信息(如程序计数器、一组寄存器和栈)。

根据进程与线程的设置,操作系统大致分为如下类型:

(1)单进程、单线程,MS-DOS大致是这种操作系统;

(2)多进程、单线程,多数UNIX(及类UNIX的LINUX)是这种操作系统;

(3)多进程、多线程,WindowsNT(以及基于NT内核的Windows2000、XP等)、Solaris2.x和OS/2都是这种操作系统;

(4)单进程、多线程,可以认为VxWorks是这种操作系统。

VxWorks只有一个进程(内存空间和资源分配),其任务的概念与线程大致相当,所有任务之间共享内存和其它资源。

3开发环境

嵌入式软件开发不同于PC机Windows操作系统之上的应用软件开发,它一般需要一个交叉编译和调试环境。

编译和调试软件运行在宿主机上(我们通常使用的PC机,Windows操作系统),它们按照目标平台CPU指令集生成目标代码,并将目标代码下载到目标机上运行;此后,主机和目标机需建立通讯连接,并传输调试命令和数据。

调试方式如下图所示:

VxWorks的开发环境为WindRiver公司提供的Tornado,它支持的目标平台可以是X86、ARM、PowerPC等类型处理器。

Tornado包含三个高度集成的部分:

(1)运行在宿主机和目标机上的强有力的交叉开发工具和实用程序;

(2)运行在目标机上的高性能、可裁剪的实时操作系统VxWorks;

(3)连接宿主机和目标机的多种通讯方式,如:

以太网,串口线,ICE或ROM仿真器等。

对于不同的目标机,Tornado给开发者提供一个一致的图形接口和人机界面,如下图所示:

我们通常需要一块目标电路板来进行嵌入式系统的开发调试工作,但是相信还有相当多的读者朋友没有目标开发电路板,为了实现本文中代码的调试,我们可采用两种方式:

(1)使用Tornado提供的VxSim模拟器来模拟调试,在此模拟器平台上,我们同样可以实现和运行本文中将介绍的大部分程序。

VxSim是一个原型仿真器,它能使开发者在没有实际目标硬件的情况下,先进行原型机应用程序的开发。

如果我们要调试BSP程序,不能依赖此平台。

其界面很简洁,如下图:

(2)使用著名的VmWare虚拟机软件虚拟一个X86目标机平台,安装对应于X86版本的Tornado,我们可以调试BSP和一般应用程序。

VMWare是一个“虚拟机”软件,它使用户可以在一台机器上同时运行多个WIN2000/WINNT/WIN9X/DOS/LINUX/VxWorks等系统。

VmWare是较“多启动”是一个更好的选择:

“多启动”系统在一个时刻只能运行一个系统,在系统切换时需要重新启动机器,而VmWare则使用运行于Windows之上,各种操作系统的切换直接在VmWare软件中进行。

VmWare的界面如下图:

Postedin3.嵌入式系统|NoComments»

 

基于嵌入式操作系统VxWorks的多任务并发程序设计

(2)--任务控制

03月5th,2006by宋宝华

基于嵌入式操作系统VxWorks的多任务并发程序设计

(2)

――任务控制

作者:

宋宝华e-mail:

21cnbao@  出处:

软件报

4任务与任务状态

VxWorks实时内核Wind提供了基本的多任务环境。

对用户而言,宏观上看起来,多个任务同时在执行。

而本质而言,在微观上,系统内核中的任务调度器总是在根据特定的调度策略让它们交替运行。

系统调度器需要使用任务控制块(TCB)数据结构来管理任务调度功能,TCB被用来描述一个任务。

TCB中存放了任务的上下文(context)信息,主要包括程序计数器PC、CPU内部寄存器、浮点寄存器、堆栈指针SP、任务信息等。

每一任务都与一个TCB关联,当执行中的任务被停止时,任务的上下文信息需要被写入TCB;而当任务被重新执行时,必须要恢复这些上下文信息。

VxWorks的一个任务可能处于如下几种状态:

Ready:

就绪状态(不是运行状态),其他资源已经就绪,仅等待CPU,当获得CPU后,就进入Running状态;

Pended:

阻塞状态,由于等待某些资源(CPU除外)而阻塞;

Suspended:

挂起状态,这种状态需要用taskResume才能恢复,主要用于调试。

不会约束状态的转换,仅仅约束任务的执行;

Delayed:

睡眠状态,任务以taskDelay主动要求等待一段时间再执行;

这些状态之间的转换关系如下:

任务状态转换

完成方式

Ready->pended

通过semTake()/msgQReceive()调用

Ready->delayed

通过taskDelay()

ready->suspended

通过taskSuspend()

pended->ready

通过其它任务对semaGive()/msgQSend()的调用

pended->suspended

通过其它任务对taskSuspend()调用

delayed->ready

延迟期满

delayed->suspended

通过taskSuspend()调用

suspended->ready

通过taskResume()/taskActivate()调用

suspended->pended

通过其它任务的taskResume()调用

suspended->delayed

通过其它任务的taskResume()调用

 

 

5任务控制

5.1创建任务

VxWorks程序员创建任务需使用如下API:

taskSpawn(char*name,intpriority,intoptions,intstackSize,

FUNCPTRentryPt,intarg1,intarg2,intarg3,

intarg4,intarg5,intarg6,intarg7,

intarg8,intarg9,intarg10);

该API的参数定义如下:

name:

任务名;

priority:

任务优先级;

options:

任务选项,下表给出了各种option及其含义:

选项

16进制值

含义

VX_FP_TASK

0×0008

执行浮点协处理

VX_NO_STACK_FILL

0×0100

不对任务堆栈填充0xee

VX_PRIVATE_ENV

0×0080

执行一个环境私有的任务

VX_UNBREAKABLE

0×0002

使任务不能断点

VX_DSP_TASK

0×0200

1=DSP协处理支持

VX_ALTIVEC_TASK

0×0400

1=ALTIVEC协处理支持

stacksize:

任务堆栈大小;

main:

任务入口函数;

arg1,…arg10:

任务入口函数参数

下面来看一个具体的例子:

例1:

创建任务

/*includes*/

#include"vxWorks.h"

#include"taskLib.h"

#include"sysLib.h"

 

 

inttid;

/*taskfunction*/

voidmyFunc(void)

{

inti;

 

 

printf("Hello,Iamtask%d\n",taskIdSelf());/*PrinttaskId*/

for(i=0;i<10;i++)

{

printf("%d",i);

taskDelay(sysClkRateGet()/2);

}

}

/*userentry*/

voiduser_start()

{

printf("readytobeginanewtask\n");

tid=taskSpawn("myTask",90,VX_NO_STACK_FILL,2000,(FUNCPTR)myFunc,0,0,0,0,0,0,0,0,0,0);

}

程序运行,在VxSim上输出:

Hello,Iamtask14870080

0123456789

taskDelay(sysClkRateGet()/2)语句的含义为将任务延迟0.5S,因此,0、1~9的数字输出之间间隔0.5S。

要特别注意taskSpawn函数的options参数,在如下几种情况下我们都要将其它options与VX_FP_TASK做“按位或”操作使得任务支持浮点运算(如果仅包含此选项,则不需进行或操作):

(1)执行浮点操作;

(2)调用返回任何浮点数的函数;

(3)调用参数为浮点数的函数。

例如下列程序启动任务的方式就不正确:

例2:

创建浮点支持任务

/*taskincludingfloatcalculate*/

voidfloatTask(void)

{

printf("%f",100/30.0);

}

/*userentry*/

voiduser_start()

{

taskSpawn("floatTask",90,VX_NO_STACK_FILL,2000,(FUNCPTR)floatTask,0,0,0,0,0,0,0,0,0,0);

}

应该将对taskSpawn函数调用的代码改为:

taskSpawn("floatTask",90,VX_NO_STACK_FILL|VX_FP_TASK,2000,floatTask,0,0,0,0,0,0,0,0,0,0);

5.2终止任务

exit( ):

终止当前任务。

这个函数是不安全的,任务终止后,其所占据的内存空间并未释放,请看下面的程序:

例3:

任务退出

/*includes*/

#include"vxWorks.h"

#include"taskLib.h"

#include"sysLib.h"

 

 

inttid;

/*taskfunction*/

voidmyFunc(void)

{

inti;

 

 

printf("Hello,Iamtask%d\n",taskIdSelf());/*PrinttaskId*/

for(i=0;i<5;i++)

{

printf("%d",i);

taskDelay(sysClkRateGet()/2);

}

exit(0);

for(i=5;i<10;i++)

{

printf("%d",i);

taskDelay(sysClkRateGet()/2);

}

}

 

 

/*userentry*/

voiduser_start()

{

printf("readytobeginanewtask\n");

tid=taskSpawn("myTask",90,0×100,2000,(FUNCPTR)myFunc,0,0,0,0,0,0,0,0,0,

0);

}

这次程序仅仅输出:

Hello,Iamtask14868640

01234

这意味着exit(0)语句之后的循环for(i=5;i<10;i++)没有被执行。

taskDelete()函数:

终止任务并释放任务占用的内存(堆栈和任务控制块空间),其原型为:

externSTATUStaskDelete(inttid);

参数tid为任务的ID。

请看下面的例子:

例4:

删除任务

/*includes*/

#include"vxWorks.h"

#include"taskLib.h"

#include"sysLib.h"

 

 

inttid;

/*taskfunction*/

voidmyFunc(void)

{

inti;

 

 

printf("Hello,Iamtask%d\n",taskIdSelf());/*PrinttaskId*/

for(i=0;i<10;i++)

{

printf("%d",i);

taskDelay(sysClkRateGet()/2);

}

}

 

 

/*anothertaskfunction:

deletemytask*/

voiddelMyTaskFunc(void)

{

taskDelay(sysClkRateGet()*4);

printf("readytodeletetask\n");

taskDelete(tid);

}

 

 

/*userentry*/

voiduser_start()

{

printf("readytobeginnewtasks\n");

tid=taskSpawn("myTask",90,0×100,2000,(FUNCPTR)myFunc,0,0,0,0,0,0,0,0,0,0);

taskSpawn("delMyTask",90,0×100,2000,(FUNCPTR)delMyTaskFunc,0,0,0,0,0,0,0,0,0,0);

}

运行输出:

Hello,Iamtask14868640

01234567readytobeginanewtask

程序为运行输出8、9,这是因为在此之前,myTask已经被另一个任务――delMyTask删除。

任务可能被taskDelete()调用删除掉,但这一行为也不一定是安全的。

如果我们删除一个获得了某些资源(如二进制信号量等)的任务,则对应的资源将不被释放,到站其它正在等待该资源的任务永远不能获得资源,系统会挡掉。

我们可以用taskSafe()和taskUnsafe()来保护这种区域,例如:

taskSafe();

semTake(semId,WAIT_FOREVER);

/*Blockuntilsemaphoreavailable*/

.. .. criticalregion.

semGive(semId); semGive(semId);  

/*Releasesemaphore*/

taskUnsafe();

5.3延迟任务

taskdelay()提供了一个简单的任务睡眠机制,常用于需要定时/延时机制的应用中。

它的原型是:

STATUStaskDelay(intticks/*numberoftickstodelaytask*/);

可以看出使用该函数实现延时的单位为节拍(tick)。

在VxWorks下通常以如下方式调用taskDelay()函数:

taskDelay(sysClkRateGet()*n);

其中的n是要延迟的时间,以秒为单位。

其中的sysClkRateGet(intticks/*numberoftickseverysecond*/)函数返回系统的时钟速率,单位是tick数/每秒。

操作系统每秒的tick数可以利用sysClkRateSet()函数设置。

5.4挂起/恢复/重启任务

我们可以使用taskSuspend()函数挂起一个任务的运行,这个任务只有获得对应的taskResume()后才能再次运行,这两个API的原型为:

externSTATUStaskSuspend(inttid);

externSTATUStaskResume(inttid);

例5:

挂起/恢复任务

/*includes*/

#include"vxWorks.h"

#include"taskLib.h"

#include"sysLib.h"

 

 

inttid;

/*taskfunction*/

voidmyFunc(void)

{

inti;

 

 

printf("Hello,Iamtask%d\n",taskIdSelf());/*PrinttaskId*/

for(i=0;i<10;i++)

{

printf("%d",i);

taskDelay(sysClkRateGet()/2);

}

}

 

 

/*suspendandresumetask*/

voidsuspendResumeMyTask(void)

{

taskDelay(sysClkRateGet()*3);

taskSuspend(tid);

printf("mytaskissuspende

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 小学教育 > 语文

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2