1 / 81

VxWorks 及其应用开发

VxWorks 及其应用开发 . 陈香兰 xlanchen@ustc.edu.cn http://staff.ustc.edu.cn/~xlanchen 2006 年 7 月. 课程内容. VxWorks 和 Tornado 简介 任务和任务间通信 信号、中断处理与定时机制 调试环境与实例分析 网络编程 VxWorks 操作系统配置. VxWorks 的任务 与任务编程接口. xlanchen@2006.7.12. 1. VxWorks 的任务 1.1 多任务. 软件设计时,通常将应用划分成独立的、相互作用的程序集合。对于每个程序,当其执行时,我们称之为任务

salvatore
Télécharger la présentation

VxWorks 及其应用开发

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. VxWorks及其应用开发 陈香兰 xlanchen@ustc.edu.cn http://staff.ustc.edu.cn/~xlanchen 2006年7月

  2. 课程内容 • VxWorks和Tornado简介 • 任务和任务间通信 • 信号、中断处理与定时机制 • 调试环境与实例分析 • 网络编程 • VxWorks操作系统配置

  3. VxWorks的任务与任务编程接口 xlanchen@2006.7.12

  4. 1. VxWorks的任务1.1 多任务 • 软件设计时,通常将应用划分成独立的、相互作用的程序集合。对于每个程序,当其执行时,我们称之为任务 • VxWorks实时内核Wind提供基本的多任务环境 • 在单CPU系统中,多任务构造出多个线程并发执行的假象 • 系统根据调度算法,调度这些任务运行

  5. 任务有自己的上下文 • 包括CPU环境、系统资源等 • 任务由系统内核调度运行 • 上下文切换时,任务的上下文保存在任务控制块(TCB)中 • 一个任务的上下文包括: • 任务的执行点(程序计数器) • CPU寄存器和浮点计数器

  6. 动态变量和函数调用的堆栈 • 标准输入/输出以及出错的I/O分配 • 一个延时定时器 • 一个时间片定时器 • 内核控制结构 • 信号处理器 • 调试和性能监视值

  7. 与Windows系统不同,VxWorks操作系统的内存是线性的与Windows系统不同,VxWorks操作系统的内存是线性的 • 使用单地址空间 • 所有代码执行在单一、公共的地址空间内 • 因此地址空间不属于任务上下文 • 当选用VxVMI时,每个任务各自的地址空间需要进行虚拟地址到物理地址的转换

  8. 1.2 任务状态转换 • 任务状态反映任务当前在系统中所处的情形 • 任务状态由内核负责维护。因此,任务状态的转换是应用调用了某些内核调用的结果

  9. 任务的状态 • 就绪(READY) • 阻塞(PEND) • 睡眠(DELAY) • 挂起(SUSPEND) • DELAY+S • PEND+S • PEND+T • PEND+S+T • State+T 任务只需要等待CPU资源 由于CPU以外的资源不可用而阻塞 任务处于睡眠状态 这种任务状态不能执行。主要用于调 试。不会约束状态转换,仅仅约束任 务的执行。因此,pended-suspended任 务仍然可以解锁,delayed-suspended 任务仍然可以唤醒 既处于睡眠状态又处于挂起状态 既处于阻塞状态又处于挂起状态 超时阻塞 超时阻塞并挂起 处于State带有一个继承优先级的任务状态

  10. 任务状态的定义

  11. 任务的状态转换图 任务创建时,处于挂起状态 挂起 要使刚创建的任务就绪, 要激活该任务 taskResume() taskResume() taskSuspend() taskSuspend() taskSuspend() taskResume()/taskActivate() 睡眠 阻塞 就绪 taskDelay() 延时已到 使用spawning原语,可以直接 创建并激活一个任务 调度 semTake()/msgQReceive() semGive()/msgQSend() 抢占 执行 任务可以在任何状态下被删除

  12. 任务状态队列

  13. 1.3 Wind任务调度 • 调度是针对多任务而言的 • 调度是指:根据一定的约束规则,将CPU分配给符合条件的任务使用 • 上述约束规则就是所谓的调度算法 • Wind内核默认采用基于优先级的抢占式调度Priority-based preemptive scheduling • 同时还使用轮转(Round-Robin)调度算法

  14. 控制任务调度的函数调用 • kernelTimeSlice() • taskPrioritySet() • taskLock() • taskUnlock() 控制轮转调度 改变任务的优先级 禁止任务调度 允许任务调度

  15. 基于优先级的抢占式任务调度 • 基于优先级的抢占式任务调度 • 系统中的每个任务都拥有一个优先级 • 任意时刻,内核将CPU分配给处于就绪态的优先级最高的任务运行 • 抢占:一旦内核发现有一个比当前正在运行的任务的优先级高的任务就绪,内核立即保存当前任务的上下文,切换到这个高优先级任务的上下文中运行

  16. 举例:

  17. Wind内核的优先级 • 256个,编号0~255 • 优先级0最高,255最低 • 任务的优先级在创建时指定 • 任务可以调用taskPrioritySet改变自己的优先级 • taskPrioritySet/Get的使用举例

  18. taskPrioritySet/Get的使用举例

  19. 轮转调度 • 轮转调度通常配合基于优先级的抢占式调度进行 • 轮转调度:让优先级相同的、处于就绪态的任务公平地共享CPU • 轮转调度使用时间片来分配CPU • 每个任务执行一个预先确定的时间段(即时间片)

  20. VxWorks中,调用函数kernelTimeSlice()来使用轮转调度VxWorks中,调用函数kernelTimeSlice()来使用轮转调度 • 参数为时间片的长度(即:在每个任务放弃CPU给另一个同优先级的任务之前,系统允许它运行的最大时间长度)

  21. 使用轮转调度算法时,每个任务都有一个运行时间计数器使用轮转调度算法时,每个任务都有一个运行时间计数器 • 随着系统时钟增加而增加 • 达到规定的值(时间片的值)时,清0 • 此时,任务放到所在优先级队列的尾部 • 一个新加入的任务放在所属优先级队列的尾部,计数器初始为0 • 当被高优先级任务抢占时,保存它的当前运行时间计数器,下次被调度时,恢复这个值

  22. 举例

  23. 抢占上锁 • 在实际应用中,有时候需要避免抢占,以免发生不合理的抢占或发生一些意想不到的情况 • Wind的调度器提供taskLock()和taskUnlock()来禁止/允许抢占 • 当一个任务调用taskLock(),将会禁止抢占,在该任务执行时,将不会发生基于优先级的抢占

  24. 注意:禁止抢占只能防止任务的上下文切换,不能禁止中断注意:禁止抢占只能防止任务的上下文切换,不能禁止中断 • 禁止抢占可以用来实现互斥 • 但是,应当尽量使禁止抢占的时间最小

  25. 1.4 任务异常处理 • 程序代码或数据的错误可能引起硬件异常状态,例如 • 非法指令 • 总线或地址错 • 除数为0 • 等等 • VxWorks的异常处理包处理这些异常

  26. 默认的异常处理 • 挂起引起异常的任务 • 保存该任务在异常点的状态 • 将关于异常的描述送到Tornado开发工具中 • 同时内核和其他任务不会被中断,系统继续执行

  27. 定制的异常处理 • VxWorks允许任务使用信号功能激活自己的异常处理程序 • 如果一个任务已经提供了一个异常的信号处理程序,系统的默认处理过程不被执行

  28. 1.5 共享代码和重入 • VxWorks提倡:单个子程序的备份或子程序库被多个不同的任务调用 • 如,许多任务会调用printf(),但是系统中只有一个备份 • 定义:一个被多个任务调用的单个备份成为共享代码 • VxWorks动态链接功能很容易实现代码共享

  29. 例如

  30. 重入 • 共享代码必须是可重入的: • 一个子程序是可重入的,如果该程序的单个备份可以被多个任务同时调用而不会发生冲突 • 典型的冲突: • 对全局或静态变量的修改 • VxWorks的很多子程序是可重入的 • 惯例:所有name_r()命名的子程序被认为是不可重入的 • VxWorks的I/O和驱动程序是可重入的

  31. 大部分VxWorks程序使用的重入机制 • 使用动态堆栈变量 • 使用信号量保护全局或静态变量 • 任务变量 • Wind推荐使用上述技术编写可重入代码

  32. 动态堆栈变量 • 许多子程序仅仅是纯代码,除了动态堆栈变量外没有自己的数据 • 这些程序除了调用者以参数形式提供的数据之外,不需要其他数据 • 例如lstLib链表操作库 • 它的程序操作由调用者提供lists和nodes • 这种程序只在自己的堆栈内进行操作

  33. 动态堆栈变量,图示

  34. 受保护的全局/静态变量 • 使用semLib中提供的信号量对全局/静态变量进行互斥保护 • 将在任务间通信中介绍信号量机制

  35. 任务变量 • 任务变量机制允许在任务上下文中定义自己的私有变量,随着上下文切换而切换 随着上下文的切换而切换

  36. 使用相同主程序的多个任务 • VxWorks可以使用同一个主程序作为几个不同的任务运行,每个任务将使用自己的堆栈和上下文,并分别传给该程序不同的参数 • 可以满足同一个程序需要以不同的参数并发执行的情况,例如 机械臂的多个连接可以使用相同 的代码joint来控制,使用关节号 来指定要操纵的连接

  37. VxWorks的系统任务 VxWorks包含以下系统任务: • 根任务tUsrRoot • 内核执行的第一个任务 • 初始化VxWorks系统的主要功能,例如 • 发起日志任务、异常处理任务、网络任务和tRlogind后台任务 • 通常,上述初始化结束之后,根任务终止并删除 • 用户可以向根任务自由的添加任何必需的初始化代码 • 阅读usrRoot代码

  38. 日志任务:tLogTask • 记录系统信息的任务 • 异常处理任务:tExcTask • 提供VxWorks异常处理包,完成在中断级不能执行的功能 • 必需具有系统最高的优先级 • 不需要挂起、删除、改变其任务的优先级

  39. 网络任务:tNetTask • 后台处理VxWorks网络需要的任务级功能处理 • 目标代理服务:tWdbTask • 当目标代理设置为运行在任务模式时,创建此任务 • 处理来自Tornado目标服务的请求 • 其他可选组件的任务 • tShell • tRlogind • tTelnetd • tPortmapd

  40. 2、VxWorks任务编程接口 • VxWorks提供丰富的任务控制功能,包含在taskLib库中 • 包括: • 任务的创建、控制和获取任务信息 • 可以在Tornado IDE提供的shell工具中交互使用这些调用

  41. taskLib库

  42. taskSpawn():创建并激活一个新任务 int taskSpawn ( char *name, /*新任务的任务名*/ int priority, /*新任务的优先级*/ int options, /*任务选项字*/ int stackSize, /*堆栈大小*/ FUNCPTR entryPt, /*新任务的入口函数*/ int arg1,arg2,arg3,arg4,arg5, /*传递给入口函数*/ int arg6,arg7,arg8,arg9,arg10 /*的10参数*/ )

  43. 在源代码中使用TaskSpawn创建新任务 • 在Tornado Shell中 • 使用TaskSpawn创建新任务 • 使用i查看系统中的任务(演示)

  44. TaskSpawn() • 创建新任务的上下文 • 堆栈、含有特定参数的入口程序调用的任务环境(入口程序通常是一个普通的程序) • 新的任务将在指定的函数入口处执行 • 任务名要便于记忆,可以是任意长度、任意内容 • 堆栈是系统资源,位于系统内存中 • 其底端是TCB和任务名 • 堆栈使用0xEE填充

  45. 堆栈示意 栈底 高地址 TCB 低地址

  46. taskSpawn()返回值 • 成功:任务ID号 • 失败:ERROR返回的ERRNOS可能有: • S_intLib_NOT_ISR_CALLABLE, /*程序不能从一个ISR中调用*/ • S_objLib_OBJ_ID_ERROR, /*不正确的任务ID*/ • S_smObjLib_NOT_INITIALIZED, /*在指定的分区中,没有足够的内存用于发起任务*/ • S_memLib_NOT_ENOUGH_MEMORY, /*没有足够的内存发起任务*/ • S_memLib_BLOCK_ERROR,  /*不能够对内存分区互斥访问*/ • S_taskLib_ILLEGAL_PRIORITY /*非法的优先级*/

  47. 初始化、激活一个任务 • taskSpawn()中包含了一些低级的操作,包括初始化和激活一个任务 • taskInit() • taskActivate()

  48. taskInit()初始化一个任务 STATUS taskInit ( WIND_TCB *pTcb, /*新任务的TCB地址*/ char *name, /*新任务的名字*/ int priority, /*新任务的优先级*/ int options, /*任务选项字*/ char *pStackBase, /*任务堆栈基地址*/ int stackSize, /*堆栈大小*/ FUNCPTR entrypt, /*任务入口*/ int arg1,arg2,arg3,arg4,arg5, /*入口参数*/ int arg6,arg7,arg8,arg9,arg10 ) 允许不指定任务名,由系统自动命名 初始化指定的内存区域作为任务的堆栈 和控制块,而不像taskSpawn()那样由系 统自动分配 可以方便应用进行调试,并将堆栈分配 在指定位置

  49. taskInit的返回值: • 成功:OK • 任务不能初始化则:ERROR可能返回的ERRNOS值有:S_intLib_NOT_ISR_CALLABLE /*程序不能从一个ISR中调用*/ S_objLib_OBJ_ID_ERROR /*不正确的任务ID*/

More Related