收藏 分享(赏)

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

上传人:dreamzhangning 文档编号:2689894 上传时间:2018-09-25 格式:DOC 页数:50 大小:366KB
下载 相关 举报
基于嵌入式操作系统VxWorks的多任务并发程序设计.doc_第1页
第1页 / 共50页
基于嵌入式操作系统VxWorks的多任务并发程序设计.doc_第2页
第2页 / 共50页
基于嵌入式操作系统VxWorks的多任务并发程序设计.doc_第3页
第3页 / 共50页
基于嵌入式操作系统VxWorks的多任务并发程序设计.doc_第4页
第4页 / 共50页
基于嵌入式操作系统VxWorks的多任务并发程序设计.doc_第5页
第5页 / 共50页
点击查看更多>>
资源描述

1、 基于嵌入式操作系统 VxWorks 的多任务并发程序设计(1)基本概念02 月 13th, 2006 by 宋宝华 作者:宋宝华 e-mail: 出处:软件报(转载请务必注明作者与出处) 1 引言 嵌入式系统定义为:嵌入到对象体系中的专用计算机系统。“嵌入性”、“专用性”与“计算机系统”是嵌入式系统的三个基本要素,对象系统则是指嵌入式系统所嵌入的宿主系统。目前,随着高端消费类电子产品(如 PDA、手机、智能家电) 的普及,嵌入式计算机系统获得了相当广泛的应用。 操作系统在嵌入式软件体系中占据着重要低位,学习和掌握相关的知识是一名嵌入式系统研发人员的必须。 1.1 本文的读者对象与写作目的 本

2、文针对的读者对象为入门级的嵌入式系统软件开发人员以及其他对嵌入式操作系统感兴趣的朋友,顺利阅读本文需要读者具备的基本知识能力为: (1)熟练的 C 语言程序设计能力; (2)操作系统的基本知识。 如果读者具备在 Windows 平台下进行多线程程序设计或者其他嵌入式操作系统本台下进行多任务程序设计的经验,将对阅读本文有很大的帮助。 本文虽然以 VxWorks 为介绍的主体对象,但是其中所论述的概念和方法并不局限于 VxWorks 操作系统本身。它们也同样适用于其它嵌入式操作系统,如WinCE、嵌入式 Linux、ucos 等,所谓“万变不离其宗”。 笔者力求能以通俗和形象的语言进行论述,但是由

3、于水平有限,文中难免存在错误和纰漏,诚盼读者朋友指正。 1.2 为什么以 VxWorks 为写作对象 之所以选择 VxWorks 操作系统为本文的写作对象,是因为: (1)VxWorks 具备清晰的多任务并发控制及任务间通信的成熟机制; (2)VxWorks 有广泛的使用基础,国内外分布着大量的 VxWorks 程序员;(3)VxWorks 简单易学,便于我们集中目标讲解多任务控制程序本身。 1.3 什么是 VxWorks VxWorks 操作系统是美国 WindRiver 公司于 1983 年设计开发的一种嵌入式实时操作系统(RTOS ),它凭借着良好的可持续发展能力、高性能的内核以及友好的

4、用户开发环境,在嵌入式实时操作系统领域占据了重要一席。VxWorks具备高可靠性和实时性,因而被广泛地应用在通信、军事、航空、航天等高精尖技术及实时性要求极高的领域中,如卫星通讯、军事演习、弹道制导、飞机导航等。在美国的 F-16、FA-18 战斗机、B-2 隐形轰炸机和爱国者导弹上,甚至连 1997 年 4 月在火星表面登陆的火星探测器上也使用到了 VxWorks。 VxWorks 的 实时性体现在它能在限定时间内执行完规定的功能并对外部的异步事件作出响应。实时操作系统主要应用于过程控制、数据采集、通信、多媒体信息处理等对时间敏 感的场合;而分时操作系统按照相等的时间片调度进程轮流运行,无法

5、实时响应外部异步事件,因而主要应用于科学计算和实时性要求不高的场合。 VxWorks 由一个体积很小的内核及一些可以根据需要进行定制的系统模块组成。VxWorks 内核最小为 8KB,即便加上其它必要模块,所占用的空间也很小,且不失其实时、多任务的系统特征。VxWorks 的内核主要包括: (1)多任务:为满足真实世界事件的异步性,现代操作系统需提供多任务支持,由系统内核分配 CPU 给多个任务并发执行。如果是单 CPU,则执行方式实质是宏观并行、微观串行; (2)任务调度:真实世界的事件具有继承的优先级,当一个高优先级的任务变为可执行态,它会立即抢占当前正在运行的较低优先级的任务,VxWor

6、ks对这种优先级抢占调度(Preemptive Priority Scheduling )提供了支持。同时,VxWorks 也支持同优先级任务间的时间片轮转调度(Round-Robin Scheduling);(3)任务间的通讯与同步:在一个实时系统中,系统必须提供多个任务间快速且功能强大的通信机制,并提供为了有效地共享不可抢占的资源或临界区所需的同步机制; (4)任务与中断之间的通信:许多外设以中断方式与 CPU 通信,我们不宜在中断服务程序(ISR )中进行过多的处理,通常将相应处理交给特定任务去完成。 VxWorks 前些年对我国一直采取禁运措施,自从对中国的销售解禁以来,它在中国赢得了

7、越来越多的用户。 2 进程、线程与任务 既然我们是讲解一种操作系统,那我们就有必要再老生长叹一次进程与线程的概念及其区别。 进程(Process) 是具有一定独立功能的程序关于某个数据集合上的一次运行活动,是系统进行资源分配和调度的一个独立单位。程序只是一组指令的有序集合,它本身没有任何运行 的含义,只是一个静态实体。而进程则不同,它是程序在某个数据集上的执行,是一个动态实体。它因创建而产生,因调度而运行,因等待资源或事件而被处于等待 状态,因完成任务而被撤消,反映了一个程序在一定的数据集上运行的全部动态过程。 线程(Thread )是进程的一个实体,是 CPU 调度和分派的基本单位。线程不能

8、够独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。线 程和进程的关系是:线程是属于进程的,线程运行在进程空间内,同一进程所产生的线程共享同一内存空间,当进程退出时该进程所产生的线程都会被强制退出并清 除。线程可与属于同一进程的其它线程共享进程所拥有的全部资源,但是其本身基本上不拥有系统资源,只拥有一点在运行中必不可少的信息(如程序计数器、一组寄存器和栈)。 根据进程与线程的设置,操作系统大致分为如下类型: (1)单进程、单线程,MS-DOS 大致是这种操作系统; (2)多进程、单线程,多数 UNIX(及类 UNIX 的 LINUX)是这种操作系统; (3)多进程、多线程,Win

9、dows NT(以及基于 NT 内核的 Windows 2000、XP 等)、Solaris 2.x 和 OS/2 都是这种操作系统; (4)单进程、多线程,可以认为 VxWorks 是这种操作系统。 VxWorks 只有一个进程(内存空间和资源分配),其任务的概念与线程大致相当,所有任务之间共享内存和其它资源。 3 开发环境 嵌入式软件开发不同于 PC 机 Windows 操作系统之上的应用软件开发,它一般需要一个交叉编译和调试环境。编译和调试软件运行在宿主机上(我们通常使用的 PC 机,Windows 操作系统),它们按照目标平台 CPU 指令集生成目标代码,并将目标代码下载到目标机上运行

10、;此后,主机和目标机需建立通讯连接,并传输调试命令和数据。调试方式如下图所示:VxWorks 的开发环境为 WindRiver 公司提供的 Tornado,它支持的目标平台可以是 X86、ARM、PowerPC 等类型处理器。Tornado 包含三个高度集成的部分: (1)运行在宿主机和目标机上的强有力的交叉开发工具和实用程序; (2)运行在目标机上的高性能、可裁剪的实时操作系统 VxWorks; (3)连接宿主机和目标机的多种通讯方式,如:以太网,串口线,ICE 或ROM 仿真器等。 对于不同的目标机,Tornado 给开发者提供一个一致的图形接口和人机界面,如下图所示:我们通常需要一块目标

11、电路板来进行嵌入式系统的开发调试工作,但是相信还有相当多的读者朋友没有目标开发电路板,为了实现本文中代码的调试,我们可采用两种方式: (1)使用 Tornado 提供的 VxSim 模拟器来模拟调试,在此模拟器平台上,我们同样可以实现和运行本文中将介绍的大部分程序。VxSim 是一个原型仿真器,它能使开发者在没有实际目标硬件的情况下,先进行原型机应用程序的开发。如果我们要调试 BSP 程序,不能依赖此平台。其界面很简洁,如下图:(2)使用著名的 VmWare 虚拟机软件虚拟一个 X86 目标机平台,安装对应于 X86 版本的 Tornado,我们可以调试 BSP 和一般应用程序。 VMWare

12、 是一个“虚拟机”软件,它使用户可以在一台机器上同时运行多个WIN2000/WINNT/WIN9X /DOS/LINUX/VxWorks 等系统。VmWare 是较“多启动”是一个更好的选择:“多启动”系统在一个时刻只能运行一个系统,在系统切换时需要重新启动机器,而 VmWare 则使用运行于 Windows 之上,各种操作系统的切换直接在 VmWare 软件中进行。VmWare 的界面如下图:Posted in 3.嵌入式系统 | No Comments 基于嵌入式操作系统 VxWorks 的多任务并发程序设计(2)任务控制03 月 5th, 2006 by 宋宝华 基于嵌入式操作系统 Vx

13、Works 的多任务并发程序设计( 2) 任务控制 作者: 宋宝华 e-mail: 出处:软件报 4 任务与任务状态 VxWorks 实时内核 Wind 提供了基本的多任务环境。对用户而言,宏观上看起来,多个任务同时在执行。而本质而言,在微观上,系统内核中的任务调度器总是在根据特定的调度策略让它们交替运行。系统调度器需要使用任务控制块(TCB)数据结构来管理任务调度功能,TCB 被用来描述一个任务。TCB中存放了任务的上下文(context) 信息,主要包括程序计数器 PC、CPU 内部寄存器、浮点寄存器、堆栈指针 SP、任务信息等。每一任务都与一个 TCB 关联,当执行中的任务被停止时,任务

14、的上下文信息需要被写入 TCB;而当任务被重新执行时,必须要恢复这些上下文信息。 VxWorks 的一个任务可能处于如下几种状态: Ready:就绪状态(不是运行状态),其他资源已经就绪,仅等待 CPU,当获得 CPU 后,就进入 Running 状态; Pended:阻塞状态,由于等待某些资源(CPU 除外)而阻塞; Suspended:挂起状态,这种状态需要用 taskResume 才能恢复,主要用于调试。不会约束状态的转换,仅仅约束任务的执行; Delayed:睡眠状态,任务以 taskDelay 主动要求等待一段时间再执行; 这些状态之间的转换关系如下: 任务状态转换 完成方式 Rea

15、dy-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()调用 suspend

16、ed-pended 通过其它任务的 taskResume()调用 suspended-delayed 通过其它任务的 taskResume()调用 5 任务控制 5.1 创建任务 VxWorks 程序员创建任务需使用如下 API:taskSpawn (char *name, int priority, int options, int stackSize, FUNCPTR entryPt, int arg1, int arg2, int arg3, int arg4, int arg5, int arg6, int arg7, int arg8, int arg9, int arg10); 该

17、 API 的参数定义如下: name:任务名; priority:任务优先级; options:任务选项,下表给出了各种 option 及其含义: 选项 16 进制值 含义 VX_FP_TASK 00008 执行浮点协处理 VX_NO_STACK_FILL 00100 不对任务堆栈填充 0xee VX_PRIVATE_ENV 00080 执行一个环境私有的任务 VX_UNBREAKABLE 00002 使任务不能断点 VX_DSP_TASK 00200 1 = DSP 协处理支持 VX_ALTIVEC_TASK 00400 1 = ALTIVEC 协处理支持 stacksize:任务堆栈大小;

18、 main:任务入口函数; arg1,arg10:任务入口函数参数 下面来看一个具体的例子: 例 1:创建任务 /* includes */ #include “vxWorks.h“ #include “taskLib.h“ #include “sysLib.h“ int tid; /* task function */ void myFunc(void) int i; printf(“Hello, I am task %dn“, taskIdSelf(); /* Print task Id */ for (i = 0; i 0) (*msgRequest.routine)(msgReques

19、t.arg); 上述程序中,pipeServer 执行于非常低的优先级(254 级),当我们在 shell 中输入“serverSend(VOIDFUNCPTR routine, int arg)” 时,pipeServer 将读到管道中的消息,并执行“*routine (arg)”。 为对此进行验证,我们在程序中再添加一个函数: void PRINT(int arg) printf(“%d“,arg); 当我们在 tShell 中输入“serverSend(PRINT,2); ”,在 VxSim 中将输出 2。 9.套接字 不论网络中的节点使用什么操作系统,套接字的通信都是完全对等的。套接字

20、有两种: (1)流套接字(SOCK_STREAM ,采用 TCP 协议):流套接字提供了双向的、有序的、无重复并且无记录边界的数据流服务; (2)数据报套接字(SOCK_DGRAM,采用 UDP 协议):数据报套接字也支持双向数据传输,但并不保证是可靠、有序和无重复的。 另外还有一种 RAW 套接字,但不常见。 VxWorks 中与 Socket 相关的函数有: (1)socket() :创建套接字 ,原型为: int socket ( int domain, /* address family (for example, AF_INET) */ int type, /* SOCK_STREA

21、M, SOCK_DGRAM, or SOCK_RAW */ int protocol /* socket protocol (usually 0) */ ); (2)bind():给套接字绑定名称 ,原型为: STATUS bind ( int s, /* socket descriptor */ struct sockaddr * name, /* name to be bound */ int namelen /* length of name */ ); (3)listen():服务端监听 TCP 连接请求,原型为: STATUS listen ( int s, /* socket de

22、scriptor */ int backlog /* number of connections to queue */ ); (4)accept():服务端接受 TCP 连接请求,原型为: int accept ( int s, /* socket descriptor */ struct sockaddr * addr, /* peer address */ int * addrlen /* peer address length */ ); (5)connect():客户端请求连接套接字,原型为: STATUS connect ( int s, /* socket descriptor

23、*/ struct sockaddr * name, /* addr of socket to connect */ int namelen /* length of name, in bytes */ ); (6)shutdown():关闭套接字间连接,原型为: STATUS shutdown ( int s, /* socket to shut down */ int how /* 0:receives disallowed;1:sends disallowed; 2:sends and receives disallowed */ ); (7)sendto()、send()、sendms

24、g():发送数据 int sendto ( int s, /* socket to send data to */ caddr_t buf, /* pointer to data buffer */ int bufLen, /* length of buffer */ int flags, /* flags to underlying protocols */ struct sockaddr * to, /* recipients address */ int tolen /* length of to sockaddr */ ); int send ( int s, /* socket to

25、 send to */ const char * buf, /* pointer to buffer to transmit */ int bufLen, /* length of buffer */ int flags /* flags to underlying protocols */ ); int sendmsg ( int sd, /* socket to send to */ struct msghdr * mp, /* scatter-gather message header */ int flags /* flags to underlying protocols */ );

26、 (8)recvfrom () 、recv ()、recvmsg ():接收数据 int recvfrom ( int s, /* socket to receive from */ char * buf, /* pointer to data buffer */ int bufLen, /* length of buffer */ int flags, /* flags to underlying protocols */ struct sockaddr * from, /* where to copy senders addr */ int * pFromLen /* value/resu

27、lt length of from */ ); int recv ( int s, /* socket to receive data from */ char * buf, /* buffer to write data to */ int bufLen, /* length of buffer */ int flags /* flags to underlying protocols */ ); int recvmsg ( int sd, /* socket to receive from */ struct msghdr * mp, /* scatter-gather message h

28、eader */ int flags /* flags to underlying protocols */ ); 限于篇幅的关系,我们在此不在列举 socket 通信的例子。但在最后一次连载的综合实例中,将包括完整的 socket 通信过程源代码。 10.信号与异常处理 信号是 VxWorks 中用于异常处理的方式,信号的驱动和执行机制有点类似于硬件中断(可以认为是一种软件上的通告,即 software notification)。信号的生存期为从“产生”到“传递”,一个“产生”而未“传递”的信号处于pending 状态。信号适宜进行异常处理,任务间的通信不要使用信号。 下面是从 Embry-Riddle Real-Time Laboratory 试验课程中获得的一个 signal的例子: 例 4:信号与异常处理/* includes */ #include “vxWorks.h“ #include “sigLib.h“ #include “taskLib.h“ #include “stdio.h“

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

当前位置:首页 > 高等教育 > 大学课件

本站链接:文库   一言   我酷   合作


客服QQ:2549714901微博号:道客多多官方知乎号:道客多多

经营许可证编号: 粤ICP备2021046453号世界地图

道客多多©版权所有2020-2025营业执照举报