版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
嵌入式操作系统第3章VxWorks任务管理1、VxWorks下的任务2、VxWorks下任务控制及任务编程3、VxWorks任务调度嵌入式操作系统第3章VxWorks任务管理1、VxWor嵌入式操作系统•重点掌握–VxWorks下任务的特点–VxWorks提供的任务控制函数及应用–VxWorks提供的任务调度策略及应用嵌入式操作系统•重点掌握–VxWorks下任务的特点嵌入式操作系统1、VxWorks下任务的特点任务运行的地址空间任务结构任务的标识任务的状态及状态转换任务的上下文切换嵌入式操作系统1、VxWorks下任务的特点任务运行的地址嵌入式操作系统•VxWorks中的wind内核为VxWorks提供了
一个高性能的实时多任务操作环境–任务管理、任务创建、任务调度、时钟、中断、内存管理•在VxWorks中,每个明显独立的程序在运行时称之为任务嵌入式操作系统•VxWorks中的wind内核为VxWor嵌入式操作系统cobble.c•四个任务–第一个任务tCosmos模拟一个中断服务程序生成新数据——cosmos()–第二个任务tSchlep收集数据——schlep()–第三个任务tCrunch处理数据,完成计算并求出一个结果——crunch()–第四个任务tMonitor监视结果值,当结果超出安全范围时,向屏幕打印报警信息——
monitor()•子函数——nodeAdd(),nodeScrap()嵌入式操作系统cobble.c•四个任务–第一个任务tC嵌入式操作系统1.1任务运行的地址空间•VxWorks操作系统采取线性单一实地址空
间模式,所有任务都运行在同一地址空间,不区分用户态和核心态嵌入式操作系统1.1任务运行的地址空间•VxWorks操嵌入式操作系统嵌入式操作系统嵌入式操作系统•VxWorks下任务具有如下特点:–任务切换时不需要进行虚拟地址空间切换–任务间可以直接共享变量,不需要通过内核在不同的地址空间复制数据–系统调用时不需要在核心态和用户态之间切换,相当于直接的函数调用嵌入式操作系统•VxWorks下任务具有如下特点:–任务嵌入式操作系统•!由于没有访问内存任何约束和保护,因而对代码质量提出了更高的要求•当选用VxVMI时,每个任务各自的地址空间需要进行虚拟地址到物理地址的转换嵌入式操作系统•!由于没有访问内存任何约束和保护,因而对代嵌入式操作系统1.2任务的结构data段数据段bss段TCB代码段堆栈段不需要进行用户、内核的区分嵌入式操作系统1.2任务的结构data段数据段bss段TC嵌入式操作系统TCB•TCB用来描述一个任务,每一任务都与一
个TCB关联•TCB用windTcb结构体来描述–VxWorks的taskLib库中定义(taskLib.h)嵌入式操作系统TCB•TCB用来描述一个任务,每一任务都与嵌入式操作系统•TCB中上下文信息包含的具体内容:–程序执行点(PC)–CPU状态,包括各种处理器特定的寄存器–––––栈任务的状态延迟定时器时间片定时器I/O操作分配的标准输入/输出,标准错误输出操作嵌入式操作系统•TCB中上下文信息包含的具体内容:–程序嵌入式操作系统–––––––内核控制结构信号处理信息错误信息调试和性能监视状态任务变量(可选)浮点上下文(可选)可扩展项(可选)嵌入式操作系统–内核控制结构嵌入式操作系统错误信息•在VxWorks中有一个全局变量errno来存放系统最近的错误状态值•每个任务TCB中都记录有一个全局errno副本—errostatus,属于任务上下文的一部分•ISR也使用独立的errno,但是ISR没有
TCB,内核为ISR在中断栈中保存和恢复
errno嵌入式操作系统错误信息•在VxWorks中有一个全局变量e嵌入式操作系统•errno的值由4个字节表示,2个高字节表示
产生错误的模块组件编码,2个低字节表示错误编号–如0x110001,表示内存不足•VxWorks提供errnoLib库用于获取和设置
任务和中断的错误状态值嵌入式操作系统•errno的值由4个字节表示,2个高字节表嵌入式操作系统任务变量•当多个任务需要同一全局变量或静态变量提供不同的值时,VxWorks提供任务变量机制来切换全局变量•任务变量机制允许在任务上下文中定义自己的私有变量,随着上下文切换而切换嵌入式操作系统任务变量•当多个任务需要同一全局变量或静态变嵌入式操作系统嵌入式操作系统嵌入式操作系统•每个任务变量允许存放一个4字节的值typedefstructtaskVar/*TASK_VAR*/{structtaskVar*next;int*address;intvalue;}TASK_VAR;•VxWorks提供库taskVarLib库支持任务变
量机制嵌入式操作系统•每个任务变量允许存放一个4字节的值type嵌入式操作系统•当有多个任务变量时,任务变量以单向链表的形式存在嵌入式操作系统•当有多个任务变量时,任务变量以单向链表嵌入式操作系统•任务切换时需要遍历任务变量链表,进行变量值的恢复和保存——降低效率•!此机制会降低任务上下文切换的效率,
建议编程时谨慎使用嵌入式操作系统•任务切换时需要遍历任务变量链表,进行•!嵌入式操作系统堆栈•在任务创建时指定堆栈的大小•TCB记录了位置和
大小等栈信息•任务栈大小的设置必须合理高地址pStackEndStackSizepStackBaseTCB低地址pTCBpTaskMem16bytes嵌入式操作系统堆栈•在任务创建时指定•任务栈大小的设置高嵌入式操作系统•VxWorks操作系统提供函数checkStack()
来检查任务栈使用情况–checkStack()显示了单个指定任务或者所有任
务的栈使用情况,包括:••••栈大小(SIZE)栈当前使用数(CUR)历史使用峰值(HIGH)最大可能空余数(MARGIN=SIZE-HIGH)•Tornado中的browser也可查看栈的使用情
况•!堆栈诊断前提:栈初始化时要用0xee填
充嵌入式操作系统•VxWorks操作系统提供函数checkS嵌入式操作系统•shell下创建任务时默认堆栈大小(sp命
令)–#defineSHELL_STACK_SIZE10000•VxWorks支持独立的中断栈,对所有的
ISR使用相同的中断栈–中断栈在系统启动时根据配置参数设置位置、大小和填充。在configAll.h中有缺省定义:#defineISR_STACK_SIZE1000嵌入式操作系统•shell下创建任务时默认堆栈大小(sp命嵌入式操作系统1.3任务的标识•VxWorks下标识任务有两种途径:任务名称和任
务ID号•任务名称–是独一无二的字符串–主机任务以字母u开头–目标机任务以字母t开头•任务ID号–长度为4字节,指向TCB•VxWorks提供任务名称和任务ID之间的转换函数嵌入式操作系统1.3任务的标识•VxWorks下标识任务嵌入式操作系统1.4任务的状态•5种基本状态:––––––––––执行(RUN)就绪(READY)——任务只需等待cpu阻塞(PEND)——有cpu以外的资源不可用睡眠(DELAY)——任务处于睡眠状态挂起(SUSPEND)——一般用于调试DELAY+S——睡眠+挂起PEND+S——阻塞+挂起状态PEND+T——延时阻塞状态PEND+T+S——延时阻塞+挂起状态…+I——继承优先级状态,优先级暂时被提升•多种组合状态嵌入式操作系统1.4任务的状态•5种基本状态:––执行(嵌入式操作系统任务的状态转换图任务创建时,处于挂起状态taskSuspend()taskResume()挂起要使刚创建的任务就绪,
taskResume()要激活该任务
taskSuspend()taskSuspend()taskResume()/taskActivate()阻塞就绪semTake()/msgQReceive()semGive()/msgQSend()抢占调度睡眠taskDelay()
使用spawning原语,可以直接延时已到创建并激活一个任务任务可以在任何状态下被删除执行嵌入式操作系统任务的状态转换图任务创建时,处于挂起状态tas嵌入式操作系统任务的状态队列嵌入式操作系统任务的状态队列嵌入式操作系统1.5任务上下文切换•上下文切换示意图TCB(Old)copyofpccopyofspCPUpcspTCB(New)copyofpccopyofsperrorStatuserrnoerrorStatus嵌入式操作系统1.5任务上下文切换•上下文切换示意图TC嵌入式操作系统•上下文切换分两种情况:同步和异步•同步上下文切换,引起的原因是当前运行的任务
执行下列操作:–进行阻塞、延迟、挂起的调用;–使更高优先级任务就绪而发生优先级抢占–降低自身优先级或者退出;•异步上下文切换,通常由ISR使更高优先级任务就
绪引起。嵌入式操作系统•上下文切换分两种情况:同步和异步–进行阻嵌入式操作系统1.6VxWorks的系统任务•根任务tUsrRoot–内核执行的第一个任务–初始化VxWorks系统的主要功能,例如•发起日志任务、异常处理任务、网络任务和
tRlogind后台任务–通常,上述初始化结束之后,根任务终止并删除–用户可以向根任务自由的添加任何必需的初始化代码–对应usrRoot()函数(target/config/all/usrConfig.c)嵌入式操作系统1.6VxWorks的系统任务•根任务tU嵌入式操作系统•日志任务:tLogTask–记录系统信息的任务。它不执行输入/输出操作。•异常处理任务:tExcTask–提供VxWorks异常处理包,完成在中断级不能执行的功能–必须具有系统最高的优先级–不能挂起、删除、改变其任务的优先级•目标代理服务:tWdbTask(INCLUDE_WDB)–当目标代理设置为运行在任务模式时,创建此任务–处理来自Tornado目标服务的请求★以上3种任务都属于VxWorks的基本任务嵌入式操作系统•日志任务:tLogTask–记录系统信息嵌入式操作系统•网络任务:tNetTask(INCLUDE_NET_LIB)
–后台处理VxWorks网络需要的任务级功能处理•其他可选组件的任务
–tShell(INCLUDE_SHELL)
–tRlogind(INCLUDE_RLOGIN)
–tTelnetd(INCLUDE_TELNET)
–tPortmapd(INCLUDE_RPC)嵌入式操作系统•网络任务:tNetTask(INCLUDE嵌入式操作系统与Linux比较•任务控制块的内容多用户性、任务间的亲属关系、文件打开表、队列信息、虚拟内存信息、错误状态等•栈栈的大小、中断栈•任务状态状态的种类、状态间的转换嵌入式操作系统与Linux比较•任务控制块的内容多用户性、嵌入式操作系统2、VxWorks下任务控制及任务编程••••••任务创建和激活任务删除与任务安全任务的状态控制任务信息的获取任务扩展函数代码的共享与重入嵌入式操作系统2、VxWorks下任务控制及任务编程•任务创嵌入式操作系统•VxWorks提供丰富的任务控制功能,包含在
taskLib库中•包括:
–任务的创建、删除、状态控制、获取任务信息等等•可以在TornadoIDE提供的shell工具中交互使用
这些调用嵌入式操作系统•VxWorks提供丰富的任务控制功能,包含嵌入式操作系统嵌入式操作系统嵌入式操作系统嵌入式操作系统嵌入式操作系统嵌入式操作系统嵌入式操作系统2.1任务的创建与激活•VxWorks的TaskLib库中提供多个函数用于创建
任务:调用taskSpawn()taskInit()taskActivate()描述创建并激活一个任务初始化一个新任务激活一个初始化任务嵌入式操作系统2.1任务的创建与激活•VxWorks的T嵌入式操作系统taskSpawn()—创建并激活一个新任务inttaskSpawn(char*name,/*新任务的任务名*/intpriority,/*新任务的优先级*/intoptions,/*任务选项字*/intstackSize,/*堆栈大小*/FUNCPTRentryPt,/*新任务的入口函数*/intarg1,arg2,arg3,arg4,arg5,/*传递给入口函数*/intarg6,arg7,arg8,arg9,arg10/*的10参数*/)嵌入式操作系统taskSpawn()—创建并激活一个新任务i嵌入式操作系统TaskSpawn()•创建新任务的上下文
–堆栈、TCB、含有特定参数的入口程序调用的任务环境(入口程序通常是一个普通的程序)
–新的任务将在指定的函数入口处执行
–激活新任务•堆栈是系统资源,位于系统内存中
–其底端是TCB–堆栈使用0xEE填充•任务名要便于记忆,可以是任意长度、任意内容嵌入式操作系统TaskSpawn()•创建新任务的上下文嵌入式操作系统•taskSpawn中的任务选项参数可以是下表中的选项之一或其组合如果任务使用任何浮点操作,必须要求使用VX_FP_TASK选项嵌入式操作系统•taskSpawn中的任务选项参数可以是下嵌入式操作系统•任务的优先级:
–Wind内核支持256种优先级,0~255
–优先级0为最高,优先级255为最低
–一般,0~99分配给系统任务,100~255分配给用户任务嵌入式操作系统•任务的优先级:嵌入式操作系统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/*非法的优先级*/嵌入式操作系统taskSpawn()返回值•成功:任务ID嵌入式操作系统•在源代码中使用TaskSpawn创建新任务•在TornadoShell中–使用TaskSpawn创建新任务–使用i查看系统中的任务(演示)嵌入式操作系统•在源代码中使用TaskSpawn创建新任务嵌入式操作系统•taskSpawn()中包含了一些低级的操作,包括初始
化和激活一个任务
–taskInit()
–taskActivate()嵌入式操作系统•taskSpawn()中包含了一些低级的操嵌入式操作系统taskInit()初始化一个任务STATUStaskInit(WIND_TCB*pTcb,/*新任务的TCB地址*/char*name,允许不指定任务名,由系统自动命名/*新任务的名字*/intpriority,/*新任务的优先级*/intoptions,/*任务选项字*/char*pStackBase,/*任务堆栈基地址*/
初始化指定的内存区域作为任务的堆栈和控制块,而不像taskSpawn()那样由系
intstackSize,/*堆栈大小*/FUNCPTRentrypt,统自动分配/*任务入口*/intarg1,arg2,arg3,arg4,arg5,/*入口参数*/
可以方便应用进行调试,并将堆栈分配在指定位置intarg6,arg7,arg8,arg9,arg10)嵌入式操作系统taskInit()初始化一个任务STATUS嵌入式操作系统•taskInit的返回值:
–成功:OK–任务不能初始化则:ERROR。可能返回的
ERRNOS值有:•S_intLib_NOT_ISR_CALLABLE/*程序不能从一个ISR中调用*/•S_objLib_OBJ_ID_ERROR/*不正确的任务ID*/嵌入式操作系统•taskInit的返回值:•S_intL嵌入式操作系统taskActivate()激活一个任务•STATUStaskActivate(inttid)•taskActivate()激活由taskInit()创建的任务,其参
数是taskInit()中第一个参数任务TCB的地址,强制类型转换如下:–tid=(int)pTcb;•注意:当应用需要对任务定位和激活进行控制时,才使用这两个函数,通常使用taskSpawn()就可以了嵌入式操作系统taskActivate()激活一个任务•S嵌入式操作系统管理任务名称和ID号的函数••••由任务号得到任务名taskName()
由任务名得到任务ID号taskNameTold()taskIDSelf()
得到任务自身的ID号taskIdVerify()
证实一个特定任务的存在(由任务ID指定)嵌入式操作系统管理任务名称和ID号的函数•嵌入式操作系统任务选项相关函数•尽管TaskSpawn()中options参数指定的新任务的选项,使用下列函数可以动态读取或设置指定任务的选项
–taskOptionsGet():获取任务选项
–taskOptionsSet():设置任务选项–当前只有VX_UNBREAKABLE选项可以改变嵌入式操作系统任务选项相关函数•尽管TaskSpawn()嵌入式操作系统获取任务信息••••••••taskIDListGet():获取所有活动任务的ID号taskInfoGet():得到指定任务的信息taskPriorityGet():查看指定任务的优先级taskRegsGet():查看任务的寄存器taskRegsSet():设置任务的寄存器taskIsSuspended():查看指定任务是否挂起taskIsReady():查看指定任务是否就绪taskTCB:得到任务控制块指针嵌入式操作系统获取任务信息•taskIDListGet():嵌入式操作系统taskSpawn应用实例1嵌入式操作系统taskSpawn应用实例1嵌入式操作系统•结果演示嵌入式操作系统•结果演示嵌入式操作系统•仿真器上显示信息:嵌入式操作系统•仿真器上显示信息:嵌入式操作系统•将s2_tasks中的优先级101改为101-i嵌入式操作系统•将s2_tasks中的优先级101改为10嵌入式操作系统•演示结果嵌入式操作系统•演示结果嵌入式操作系统taskSpawn应用实例2嵌入式操作系统taskSpawn应用实例2嵌入式操作系统•演示结果嵌入式操作系统•演示结果嵌入式操作系统•仿真器上显示信息:嵌入式操作系统•仿真器上显示信息:嵌入式操作系统2.2任务删除和删除安全•任务可以动态地从系统中删除•删除任务的函数调用若任务的入口函数指定返回,则将隐含调用exit();另外,任务可以在任何时候调用exit杀死自身;–exit():终止任务自身的执行,释放所占用的
内存(stack和TCB)–taskDelete():终止一个指定任务,释放所占
用的内存(同上)任务可以在任何时候调用taskDelete删除其他任务任务终止时,其执行时任务分配的内存不会被释放,如malloc()分配的内存,必须由任务自身编程释放。嵌入式操作系统2.2任务删除和删除安全•任务可以动态地从嵌入式操作系统taskDelete应用实例延迟0.5秒嵌入式操作系统taskDelete应用实例延迟0.5秒嵌入式操作系统嵌入式操作系统嵌入式操作系统•演示结果嵌入式操作系统•演示结果嵌入式操作系统•仿真器上显示信息:嵌入式操作系统•仿真器上显示信息:嵌入式操作系统•注意:不要在一个不合适的时刻删除任务,在删除之前,该任务必须释放它所持有的所有资源•保护任务不被删除的函数调用任务访问临界区时就需要这种保护。例如,为了对某些数据结构互斥访问,任务可能取得一个信号量。但若正在临界区执行的任务被删除,会导致这个任务无法完成临界区的访问,从而使得该数据结构可能处于一种被破坏或不一致的状–taskSafe():保护任务不被删除态。–taskUnsafe():解除任务保护此外,由于该任务没有释放信号量,其他任务将无法获得信号量,从而导致该临界资源不可用。使用taskDelete()删除另一个被保护的任务,会导致调用者任务被阻塞,直到被保护的任务解除保护任务保护使用一个计数器实现保护的嵌套,仅当计数器为0时才真正的解除保护嵌入式操作系统•注意:不要在一个不合适的时刻删除任务,在删嵌入式操作系统•下面的代码段说明如何使用taskSafe()和
taskUnsafe()来保护一段临界区代码taskSafe();semTake(semID,WAIT_FOREVER);/*Blockuntilsemaphoreavailable*/…临界区操作代码…semGive(semID);/*Releasesemaphore*/taskUnsafe();嵌入式操作系统•下面的代码段说明如何使用taskSafe(嵌入式操作系统2.3任务运行的控制•下列函数用于控制任务的执行VxWorks的调试功能希望能够挂起/恢复任务的执行,从而可以冻结任务的执行状态终止任务,然后使用原有参数重新创建任务。提供一个简单的任务睡眠机制。区别,taskDelay()将会导致任务被移到相同优先级就绪队列的尾这是一个POSIX函数,部,例如taskDelay(0)可以将CPU交给同优先级的另一个任务与taskDelay()
以下调用将任务延时半秒:一样可以实现延时,但延时单位不同,可以直接指明延时。而调用nanosleep实现延时0被认为是错误的嵌入式操作系统2.3任务运行的控制•下列函数用于控制任务嵌入式操作系统taskResume()taskSuspend()taskResume()/taskActivate()taskSuspend()taskSuspend()taskResume()挂起阻塞就绪睡眠taskDelay()延时已到执行taskRestart()嵌入式操作系统taskResume()taskResume(嵌入式操作系统应用实例1嵌入式操作系统应用实例1嵌入式操作系统嵌入式操作系统嵌入式操作系统嵌入式操作系统嵌入式操作系统•演示结果嵌入式操作系统•演示结果嵌入式操作系统•仿真器上显示信息:嵌入式操作系统•仿真器上显示信息:嵌入式操作系统•将taskResume换成taskActivate,结果一样嵌入式操作系统•将taskResume换成taskActi嵌入式操作系统应用实例2嵌入式操作系统应用实例2嵌入式操作系统不能延迟到myFunc任务已结束嵌入式操作系统不能延迟到myFunc任务已结束嵌入式操作系统•演示结果嵌入式操作系统•演示结果嵌入式操作系统•仿真器上显示信息:嵌入式操作系统•仿真器上显示信息:嵌入式操作系统2.4任务扩展函数•有时任务需要在任务创建、删除或上下文切换时增加相应的处理,又不需要修改内核
VxWorks的内核wind提供钩子函数机制实现上
述目标,使得当任务创建、上下文切换、删除时调用用户附加的函数•下列函数可以设置任务创建/切换/删除时的钩子函数嵌入式操作系统2.4任务扩展函数•有时任务需要在任务创建嵌入式操作系统taskHookLib所有HOOK函数的入参都是函数指针嵌入式操作系统taskHookLib所有HOOK函数的入参都嵌入式操作系统–由于用于任务切换时的钩子函数只能运行在内核上下文中,因此这个钩子函数能够调用的函数调用有限制,只能是:缓冲区管理库协处理器(浮点)状态的保存和恢复链表操作库体系结构无关的中断例程库
C的数学计算库环形缓冲区操作库任务管理库出错处理嵌入式操作系统–由于用于任务切换时的钩子函数只能运行在内缓嵌入式操作系统应用实例嵌入式操作系统应用实例嵌入式操作系统在任务创建时,就会调用myTaskHook•演示结果
–Shell下输出信息:嵌入式操作系统在任务创建时,就会调用myTaskHook•嵌入式操作系统–仿真器输出信息:嵌入式操作系统–仿真器输出信息:嵌入式操作系统2.5代码的共享和重入•VxWorks提倡:单个子程序的备份或子程序库被多个不同的任务调用•定义:一个被多个任务调用的单个备份成为共享代码VxWorks动态链接功能很容易实现代码共享嵌入式操作系统2.5代码的共享和重入•VxWorks提倡嵌入式操作系统重入•共享代码必须是可重入的:
–一个子程序是可重入的,如果该程序的单个备份可以被多个任务同时调用而不会发生冲突•典型的冲突:
–对全局或静态变量的修改•VxWorks的很多子程序是可重入的
–惯例:所有somename_r()命名的子程序被认为是不可重入的
–VxWorks的I/O和驱动程序是可重入的嵌入式操作系统重入•共享代码必须是可重入的:嵌入式操作系统•大部分VxWorks函数使用下列3种重入技术:•动态堆栈变量–这种函数一般是纯代码,除动态堆栈变量外没有自己的数据,以调用者提供的数据为参数进行操作。•受信号量保护的全局和静态变量–这种函数一般含有公共数据,在调用时,必须借助于互斥机制,禁止任务同时在代码临界区域内执行,明确地实现重入。•任务变量–一些可被多个任务同时调用的程序,程序中的全局变量或静态变量对每次任务的调用需要不同的值。嵌入式操作系统•大部分VxWorks函数使用下列3种重入技嵌入式操作系统VxWorks与Linux比较•任务创建函数:taskSpawn()与fork()/exec()–在fork/exec模型下,先调用fork函数为新任务创建一份与父任务完全相同的内存空间,后调用exec函数装入新任务代码,并用它来覆盖原有的属于父任务的内容。这样做的好处是如果需要,可以从父任务那里继承代码、数据等属性。–在spawn模型下,摈弃了继承的功能,在创建新任务时,直接为它分配全新的地址空间,然后将新代码装入并运行。嵌入式操作系统VxWorks与Linux比较•任务创建函数嵌入式操作系统3、VxWorks任务调度•任务调度策略•任务调度时机•抢占上锁嵌入式操作系统3、VxWorks任务调度•任务调度策略嵌入式操作系统3.1任务调度策略•调度是针对多任务而言的•调度是指:根据一定的约束规则,将CPU分配给符合条件的任务使用•上述约束规则就是所谓的调度策略(或算法)•Wind内核默认采用基于优先级的抢占式调度
Priority-basedpreemptivescheduling•同时还使用轮转(Round-Robin)调度算法嵌入式操作系统3.1任务调度策略•调度是针对多任务而言的嵌入式操作系统任务队列•activeQHead–记录了一个线程从生成到删除过程中的每一个任务信息,是一个FIFO队列•readyQHead–记录所有就绪任务,是一个优先级队列•tickQHead–记录所有延迟状态的任务,是一个优先级队列•pendQHead–记录所有阻塞状态的任务,是一个优先级队列•WorkQ–记录所有中断发起的任务,是一个环形队列嵌入式操作系统任务队列•activeQHead–记录了一嵌入式操作系统控制任务调度的几个函数•kernelTimeSlice()•taskPrioritySet()•taskLock()•taskUnlock()控制轮转调度改变任务的优先级禁止任务调度允许任务调度嵌入式操作系统控制任务调度的几个函数•kernelTime嵌入式操作系统基于优先级的抢占式任务调度•基于优先级的抢占式任务调度
–系统中的每个任务都拥有一个优先级
–任意时刻,内核将CPU分配给处于就绪态的优先级最高的任务运行•抢占:
一旦内核发现有一个比当前正在运行的任务的优先级高的任务就绪,内核立即保存当前任务的上下文,切换到这个高优先级任务的上下文中运行嵌入式操作系统基于优先级的抢占式任务调度•基于优先级的抢占嵌入式操作系统嵌入式操作系统嵌入式操作系统任务优先级•VxWorks支持256个优先级,编号0~255,优先级0
最高,255最低,一般0~99分配给系统任务,
100~255分配给用户任务。•任务的优先级在创建时指定•任务可以调用taskPrioritySet改变自己的优先级嵌入式操作系统任务优先级•VxWorks支持256个优先级嵌入式操作系统应用示例•下面程序,创建了3个优先级各不相同的任务:嵌入式操作系统应用示例•下面程序,创建了3个优先级各不相同嵌入式操作系统嵌入式操作系统嵌入式操作系统嵌入式操作系统嵌入式操作系统嵌入式操作系统嵌入式操作系统•演示结果:嵌入式操作系统•演示结果:嵌入式操作系统•如何修改程序,使得任务的执行顺序变为:
taskOne,taskTwo,taskThree?嵌入式操作系统•如何修改程序,使得任务的执行顺序变为:嵌入式操作系统•修改程序,使得taskOne、taskTwo同时具有最高优先级运行:嵌入式操作系统•修改程序,使得taskOne、taskTw嵌入式操作系统•演示结果嵌入式操作系统•演示结果嵌入式操作系统•基于优先级的抢占是任务调度的缺陷:当多个相同优先级的任务需要共享一台处理器时,如果某个执行的任务永不阻塞,那么他将一直独占处理器,其它相同优先级的任务就没有机会执行。嵌入式操作系统•基于优先级的抢占是任务调度的缺陷:嵌入式操作系统轮转调度•轮转调度通常配合基于优先级的抢占式调度进行•轮转调度:让优先级相同的、处于就绪态的任务
公平地共享CPU•轮转调度使用时间片来分配CPU
–每个任务执行一个预先确定的时间段(即时间片)•在大多数系统里,并不一定需要使用轮转调度算法。但在相同代码被多份复制执行时,如在用户接口任务内执行时,需要使用轮转调度算法嵌入式操作系统轮转调度•轮转调度通常配合基于优先级的抢占式嵌入式操作系统•VxWorks中,调用函数kernelTimeSlice()来实现
轮转调度
–此函数位于kernelLib库中
–参数为时间片的长度(tick数)(即:在某个任务放弃CPU给另一个同优先级的任务之前,系统允许它运行的最大时间长度)如kernelTimeSlice(sysClkRateGet()/2)表示时间片为0.5秒
–kernelTimeSlice(0)——关闭时间片轮转调度策
略嵌入式操作系统•VxWorks中,调用函数kernelTi嵌入式操作系统•使用轮转调度算法时,每个任务都有一个运行时
间计数器–随着系统时钟增加而增加–达到规定的值(时间片的值)时,清0
•此时,任务放到所在优先级队列的尾部–一个新加入的任务放在所属优先级队列的尾部,计数器初始为0–当任务被阻塞或者被更高优先级的任务抢占,将保存其时间计数值,并且在其重新执行时恢复计数嵌入式操作系统•使用轮转调度算法时,每个任务都有一个运行时嵌入式操作系统嵌入式操作系统嵌入式操作系统应用实例•下面的例子创建三个优先级相同的任务,分别向控制台输出他们的任务id号和任务名。–s5_rrsched()调用kernelTimeSlice()允许系统使用轮转调
度。–本例中使用的时间片TIMESLICE为1/60秒(函数
sysClkRateGet()返回每秒的时钟tick数)–在设置了调度时间片后,程序发起三个任务,注意:必须保证发起的任务优先级要低于100。–另外为了演示时间片轮转的效果,要保证任务具有足够的执行时间,在本例中使用一个循环次数为
LONG_TIME的长循环。嵌入式操作系统应用实例•下面的例子创建三个优先级相同的任务嵌入式操作系统嵌入式操作系统嵌入式操作系统嵌入式操作系统嵌入式操作系统嵌入式操作系统嵌入式操作系统嵌入式操作系统嵌入式操作系统•演示结果:嵌入式操作系统•演示结果:嵌入式操作系统•增加第四个任务,其优先级为80,他和其他任务输出相同的信息。嵌入式操作系统•增加第四个任务,其优先级为80,他和其他任嵌入式操作系统•取消时间片轮转:
–第一种方法:–第二种方法:嵌入式操作系统•取消时间片轮转:–第二种方法:嵌入式操作系统•演示结果嵌入式操作系统•演示结果嵌入式操作系统任务切换•任务切换:终止正在运行的任务(当前任务),转而去运行另外一个任务•任务的切换实质就是断点数据的切换,需要完成以下工作:把被终止的任务断点指针(PC)保存到任务堆栈中把处理器通用寄存器的内容保存到任务堆栈中把被终止的任务堆栈指针当前值(SP)保存到该任务的TCB中获得待运行任务的TCB
使处理器通过TCB获得待运行任务的SP
把待运行任务堆栈中通用寄存器的内容回复到处理器的通用寄存器中–使处理器获得待运行任务的断点指针(PC)––––––嵌入式操作系统任务切换•任务切换:终止正在运行的任务(当前嵌入式操作系统3.2任务调度时机本章难点•三个关键函数–reschedule–intExit–windExit嵌入式操作系统3.2任务调度时机本章难点•三个关键函数–嵌入式操作系统•调度时机–––––––––任务相关的操作:生成/删除/挂起/恢/Lock/Unlock..WD的创建/开始和销毁TICK时钟中断信号量的某些操作Give/TakeEvent的发送和接受MsgQ销毁Posix消息队列的销毁/接受和发送Posix的mutex的销毁/锁定/解锁…中断执行退出…嵌入式操作系统•调度时机–任务相关的操作:生成/删除/挂起嵌入式操作系统任务管理中函数之间的关系嵌入式操作系统任务管理中函数之间的关系嵌入式操作系统3.3抢占上锁•在实际应用中,有时候需要避免抢占,以免发生不合理的抢占或发生一些意想不到的情况•Wind的调度器提供taskLock()和taskUnlock()来禁
止/允许抢占:嵌入式操作系统3.3抢占上锁•在实际应用中,有时候需要避嵌入式操作系统•当一个任务调用taskLock(),将会禁止抢占,在该任务执行时,将不会发生基于优先级的抢占•注意:禁止抢占只能防止任务的上下文切换,不能禁止中断•禁止抢占可以用来实现互斥•但是,应当尽量使禁止抢占的时间最小嵌入式操作系统•当一个任务调用taskLock(),将会禁嵌入式操作系统任务调度方面与Linux的比较•任务的实时优先级数–VxWorks任务的优先级0~255,数值越小优先级越高–Linux的实时进程优先级0~99,数值越大优先级越高•调度策略的种类–Linux支持SCHED_RR、SCHED_FIFO、
SCHED_OTHER三种调度策略–VxWorks只支持前两种嵌入式操作系统任务调度方面与Linux的比较•任务的实时优嵌入式操作系统•调度策略所基于的对象–VxWorks的调度策略不是基于某个任务的,而是针对
整个系统的所有任务–Linux的调度策略是基于进程的,某个进程的调度策略
的设置不影响其他进程嵌入式操作系统•调度策略所基于的对象–VxWorks的调嵌入式操作系统嵌入式操作系统嵌入式操作系统第3章VxWorks任务管理1、VxWorks下的任务2、VxWorks下任务控制及任务编程3、VxWorks任务调度嵌入式操作系统第3章VxWorks任务管理1、VxWor嵌入式操作系统•重点掌握–VxWorks下任务的特点–VxWorks提供的任务控制函数及应用–VxWorks提供的任务调度策略及应用嵌入式操作系统•重点掌握–VxWorks下任务的特点嵌入式操作系统1、VxWorks下任务的特点任务运行的地址空间任务结构任务的标识任务的状态及状态转换任务的上下文切换嵌入式操作系统1、VxWorks下任务的特点任务运行的地址嵌入式操作系统•VxWorks中的wind内核为VxWorks提供了
一个高性能的实时多任务操作环境–任务管理、任务创建、任务调度、时钟、中断、内存管理•在VxWorks中,每个明显独立的程序在运行时称之为任务嵌入式操作系统•VxWorks中的wind内核为VxWor嵌入式操作系统cobble.c•四个任务–第一个任务tCosmos模拟一个中断服务程序生成新数据——cosmos()–第二个任务tSchlep收集数据——schlep()–第三个任务tCrunch处理数据,完成计算并求出一个结果——crunch()–第四个任务tMonitor监视结果值,当结果超出安全范围时,向屏幕打印报警信息——
monitor()•子函数——nodeAdd(),nodeScrap()嵌入式操作系统cobble.c•四个任务–第一个任务tC嵌入式操作系统1.1任务运行的地址空间•VxWorks操作系统采取线性单一实地址空
间模式,所有任务都运行在同一地址空间,不区分用户态和核心态嵌入式操作系统1.1任务运行的地址空间•VxWorks操嵌入式操作系统嵌入式操作系统嵌入式操作系统•VxWorks下任务具有如下特点:–任务切换时不需要进行虚拟地址空间切换–任务间可以直接共享变量,不需要通过内核在不同的地址空间复制数据–系统调用时不需要在核心态和用户态之间切换,相当于直接的函数调用嵌入式操作系统•VxWorks下任务具有如下特点:–任务嵌入式操作系统•!由于没有访问内存任何约束和保护,因而对代码质量提出了更高的要求•当选用VxVMI时,每个任务各自的地址空间需要进行虚拟地址到物理地址的转换嵌入式操作系统•!由于没有访问内存任何约束和保护,因而对代嵌入式操作系统1.2任务的结构data段数据段bss段TCB代码段堆栈段不需要进行用户、内核的区分嵌入式操作系统1.2任务的结构data段数据段bss段TC嵌入式操作系统TCB•TCB用来描述一个任务,每一任务都与一
个TCB关联•TCB用windTcb结构体来描述–VxWorks的taskLib库中定义(taskLib.h)嵌入式操作系统TCB•TCB用来描述一个任务,每一任务都与嵌入式操作系统•TCB中上下文信息包含的具体内容:–程序执行点(PC)–CPU状态,包括各种处理器特定的寄存器–––––栈任务的状态延迟定时器时间片定时器I/O操作分配的标准输入/输出,标准错误输出操作嵌入式操作系统•TCB中上下文信息包含的具体内容:–程序嵌入式操作系统–––––––内核控制结构信号处理信息错误信息调试和性能监视状态任务变量(可选)浮点上下文(可选)可扩展项(可选)嵌入式操作系统–内核控制结构嵌入式操作系统错误信息•在VxWorks中有一个全局变量errno来存放系统最近的错误状态值•每个任务TCB中都记录有一个全局errno副本—errostatus,属于任务上下文的一部分•ISR也使用独立的errno,但是ISR没有
TCB,内核为ISR在中断栈中保存和恢复
errno嵌入式操作系统错误信息•在VxWorks中有一个全局变量e嵌入式操作系统•errno的值由4个字节表示,2个高字节表示
产生错误的模块组件编码,2个低字节表示错误编号–如0x110001,表示内存不足•VxWorks提供errnoLib库用于获取和设置
任务和中断的错误状态值嵌入式操作系统•errno的值由4个字节表示,2个高字节表嵌入式操作系统任务变量•当多个任务需要同一全局变量或静态变量提供不同的值时,VxWorks提供任务变量机制来切换全局变量•任务变量机制允许在任务上下文中定义自己的私有变量,随着上下文切换而切换嵌入式操作系统任务变量•当多个任务需要同一全局变量或静态变嵌入式操作系统嵌入式操作系统嵌入式操作系统•每个任务变量允许存放一个4字节的值typedefstructtaskVar/*TASK_VAR*/{structtaskVar*next;int*address;intvalue;}TASK_VAR;•VxWorks提供库taskVarLib库支持任务变
量机制嵌入式操作系统•每个任务变量允许存放一个4字节的值type嵌入式操作系统•当有多个任务变量时,任务变量以单向链表的形式存在嵌入式操作系统•当有多个任务变量时,任务变量以单向链表嵌入式操作系统•任务切换时需要遍历任务变量链表,进行变量值的恢复和保存——降低效率•!此机制会降低任务上下文切换的效率,
建议编程时谨慎使用嵌入式操作系统•任务切换时需要遍历任务变量链表,进行•!嵌入式操作系统堆栈•在任务创建时指定堆栈的大小•TCB记录了位置和
大小等栈信息•任务栈大小的设置必须合理高地址pStackEndStackSizepStackBaseTCB低地址pTCBpTaskMem16bytes嵌入式操作系统堆栈•在任务创建时指定•任务栈大小的设置高嵌入式操作系统•VxWorks操作系统提供函数checkStack()
来检查任务栈使用情况–checkStack()显示了单个指定任务或者所有任
务的栈使用情况,包括:••••栈大小(SIZE)栈当前使用数(CUR)历史使用峰值(HIGH)最大可能空余数(MARGIN=SIZE-HIGH)•Tornado中的browser也可查看栈的使用情
况•!堆栈诊断前提:栈初始化时要用0xee填
充嵌入式操作系统•VxWorks操作系统提供函数checkS嵌入式操作系统•shell下创建任务时默认堆栈大小(sp命
令)–#defineSHELL_STACK_SIZE10000•VxWorks支持独立的中断栈,对所有的
ISR使用相同的中断栈–中断栈在系统启动时根据配置参数设置位置、大小和填充。在configAll.h中有缺省定义:#defineISR_STACK_SIZE1000嵌入式操作系统•shell下创建任务时默认堆栈大小(sp命嵌入式操作系统1.3任务的标识•VxWorks下标识任务有两种途径:任务名称和任
务ID号•任务名称–是独一无二的字符串–主机任务以字母u开头–目标机任务以字母t开头•任务ID号–长度为4字节,指向TCB•VxWorks提供任务名称和任务ID之间的转换函数嵌入式操作系统1.3任务的标识•VxWorks下标识任务嵌入式操作系统1.4任务的状态•5种基本状态:––––––––––执行(RUN)就绪(READY)——任务只需等待cpu阻塞(PEND)——有cpu以外的资源不可用睡眠(DELAY)——任务处于睡眠状态挂起(SUSPEND)——一般用于调试DELAY+S——睡眠+挂起PEND+S——阻塞+挂起状态PEND+T——延时阻塞状态PEND+T+S——延时阻塞+挂起状态…+I——继承优先级状态,优先级暂时被提升•多种组合状态嵌入式操作系统1.4任务的状态•5种基本状态:––执行(嵌入式操作系统任务的状态转换图任务创建时,处于挂起状态taskSuspend()taskResume()挂起要使刚创建的任务就绪,
taskResume()要激活该任务
taskSuspend()taskSuspend()taskResume()/taskActivate()阻塞就绪semTake()/msgQReceive()semGive()/msgQSend()抢占调度睡眠taskDelay()
使用spawning原语,可以直接延时已到创建并激活一个任务任务可以在任何状态下被删除执行嵌入式操作系统任务的状态转换图任务创建时,处于挂起状态tas嵌入式操作系统任务的状态队列嵌入式操作系统任务的状态队列嵌入式操作系统1.5任务上下文切换•上下文切换示意图TCB(Old)copyofpccopyofspCPUpcspTCB(New)copyofpccopyofsperrorStatuserrnoerrorStatus嵌入式操作系统1.5任务上下文切换•上下文切换示意图TC嵌入式操作系统•上下文切换分两种情况:同步和异步•同步上下文切换,引起的原因是当前运行的任务
执行下列操作:–进行阻塞、延迟、挂起的调用;–使更高优先级任务就绪而发生优先级抢占–降低自身优先级或者退出;•异步上下文切换,通常由ISR使更高优先级任务就
绪引起。嵌入式操作系统•上下文切换分两种情况:同步和异步–进行阻嵌入式操作系统1.6VxWorks的系统任务•根任务tUsrRoot–内核执行的第一个任务–初始化VxWorks系统的主要功能,例如•发起日志任务、异常处理任务、网络任务和
tRlogind后台任务–通常,上述初始化结束之后,根任务终止并删除–用户可以向根任务自由的添加任何必需的初始化代码–对应usrRoot()函数(target/config/all/usrConfig.c)嵌入式操作系统1.6VxWorks的系统任务•根任务tU嵌入式操作系统•日志任务:tLogTask–记录系统信息的任务。它不执行输入/输出操作。•异常处理任务:tExcTask–提供VxWorks异常处理包,完成在中断级不能执行的功能–必须具有系统最高的优先级–不能挂起、删除、改变其任务的优先级•目标代理服务:tWdbTask(INCLUDE_WDB)–当目标代理设置为运行在任务模式时,创建此任务–处理来自Tornado目标服务的请求★以上3种任务都属于VxWorks的基本任务嵌入式操作系统•日志任务:tLogTask–记录系统信息嵌入式操作系统•网络任务:tNetTask(INCLUDE_NET_LIB)
–后台处理VxWorks网络需要的任务级功能处理•其他可选组件的任务
–tShell(INCLUDE_SHELL)
–tRlogind(INCLUDE_RLOGIN)
–tTelnetd(INCLUDE_TELNET)
–tPortmapd(INCLUDE_RPC)嵌入式操作系统•网络任务:tNetTask(INCLUDE嵌入式操作系统与Linux比较•任务控制块的内容多用户性、任务间的亲属关系、文件打开表、队列信息、虚拟内存信息、错误状态等•栈栈的大小、中断栈•任务状态状态的种类、状态间的转换嵌入式操作系统与Linux比较•任务控制块的内容多用户性、嵌入式操作系统2、VxWorks下任务控制及任务编程••••••任务创建和激活任务删除与任务安全任务的状态控制任务信息的获取任务扩展函数代码的共享与重入嵌入式操作系统2、VxWorks下任务控制及任务编程•任务创嵌入式操作系统•VxWorks提供丰富的任务控制功能,包含在
taskLib库中•包括:
–任务的创建、删除、状态控制、获取任务信息等等•可以在TornadoIDE提供的shell工具中交互使用
这些调用嵌入式操作系统•VxWorks提供丰富的任务控制功能,包含嵌入式操作系统嵌入式操作系统嵌入式操作系统嵌入式操作系统嵌入式操作系统嵌入式操作系统嵌入式操作系统2.1任务的创建与激活•VxWorks的TaskLib库中提供多个函数用于创建
任务:调用taskSpawn()taskInit()taskActivate()描述创建并激活一个任务初始化一个新任务激活一个初始化任务嵌入式操作系统2.1任务的创建与激活•VxWorks的T嵌入式操作系统taskSpawn()—创建并激活一个新任务inttaskSpawn(char*name,/*新任务的任务名*/intpriority,/*新任务的优先级*/intoptions,/*任务选项字*/intstackSize,/*堆栈大小*/FUNCPTRentryPt,/*新任务的入口函数*/intarg1,arg2,arg3,arg4,arg5,/*传递给入口函数*/intarg6,arg7,arg8,arg9,arg10/*的10参数*/)嵌入式操作系统taskSpawn()—创建并激活一个新任务i嵌入式操作系统TaskSpawn()•创建新任务的上下文
–堆栈、TCB、含有特定参数的入口程序调用的任务环境(入口程序通常是一个普通的程序)
–新的任务将在指定的函数入口处执行
–激活新任务•堆栈是系统资源,位于系统内存中
–其底端是TCB–堆栈使用0xEE填充•任务名要便于记忆,可以是任意长度、任意内容嵌入式操作系统TaskSpawn()•创建新任务的上下文嵌入式操作系统•taskSpawn中的任务选项参数可以是下表中的选项之一或其组合如果任务使用任何浮点操作,必须要求使用VX_FP_TASK选项嵌入式操作系统•taskSpawn中的任务选项参数可以是下嵌入式操作系统•任务的优先级:
–Wind内核支持256种优先级,0~255
–优先级0为最高,优先级255为最低
–一般,0~99分配给系统任务,100~255分配给用户任务嵌入式操作系统•任务的优先级:嵌入式操作系统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/*非法的优先级*/嵌入式操作系统taskSpawn()返回值•成功:任务ID嵌入式操作系统•在源代码中使用TaskSpawn创建新任务•在TornadoShell中–使用TaskSpawn创建新任务–使用i查看系统中的任务(演示)嵌入式操作系统•在源代码中使用TaskSpawn创建新任务嵌入式操作系统•taskSpawn()中包含了一些低级的操作,包括初始
化和激活一个任务
–taskInit()
–taskActivate()嵌入式操作系统•taskSpawn()中包含了一些低级的操嵌入式操作系统taskInit()初始化一个任务STATUStaskInit(WIND_TCB*pTcb,/*新任务的TCB地址*/char*name,允许不指定任务名,由系统自动命名/*新任务的名字*/intpriority,/*新任务的优先级*/intoptions,/*任务选项字*/char*pStackBase,/*任务堆栈基地址*/
初始化指定的内存区域作为任务的堆栈和控制块,而不像taskSpawn()那样由系
intstackSize,/*堆栈大小*/FUNCPTRentrypt,统自动分配/*任务入口*/intarg1,arg2,arg3,arg4,arg5,/*入口参数*/
可以方便应用进行调试,并将堆栈分配在指定位置intarg6,arg7,arg8,arg9,arg10)嵌入式操作系统taskInit()初始化一个任务STATUS嵌入式操作系统•taskInit的返回值:
–成功:OK–任务不能初始化则:ERROR。可能返回的
ERRNOS值有:•S_intLib_NOT_ISR_CALLABLE/*程序不能从一个ISR中调用*/•S_objLib_OBJ_ID_ERROR/*不正确的任务ID*/嵌入式操作系统•taskInit的返回值:•S_intL嵌入式操作系统taskActivate()激活一个任务•STATUStaskActivate(inttid)•taskActivate()激活由taskInit()创建的任务,其参
数是taskInit()中第一个参数任务TCB的地址,强制类型转换如下:–tid=(int)pTcb;•注意:当应用需要对任务定位和激活进行控制时,才使用这两个函数,通常使用taskSpawn()就可以了嵌入式操作系统taskActivate()激活一个任务•S嵌入式操作系统管理任务名称和ID号的函数••••由任务号得到任务名taskName()
由任务名得到任务ID号taskNameTold()taskIDSelf()
得到任务自身的ID号taskIdVerify()
证实一个特定任务的存在(由任务ID指定)嵌入式操作系统管理任务名称和ID号的函数•嵌入式操作系统任务选项相关函数•尽管TaskSpawn()中options参数指定的新任务的选项,使用下列函数可以动态读取或设置指定任务的选项
–taskOptionsGet():获取任务选项
–taskOptionsSet():设置任务选项–当前只有VX_UNBREAKABLE选项可以改变嵌入式操作系统任务选项相关函数•尽管TaskSpawn()嵌入式操作系统获取任务信息••••••••taskIDListGet():获取所有活动任务的ID号taskInfoGet():得到指定任务的信息taskPriorityGet():查看指定任务的优先级taskRegsGet():查看任务的寄存器taskRegsSet():设置任务的寄存器taskIsSuspended():查看指定任务是否挂起taskIsReady():查看指定任务是否就绪taskTCB:得到任务控制块指针嵌入式操作系统获取任务信息•taskIDListG
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 陕西省汉中市汉台区2023-2024学年高三上学期1月期末考试 英语 含答案
- 如何规划部门发展图文
- 专利转让协议
- 影视制作材料招投标文件
- 展览馆绿化工程施工合同样本
- 设立分公司短期合作协议
- 市场营销策略建议管理规定
- 消防应急油罐车租赁服务合同
- 生态修复草坪施工协议
- 公园绿化建设项目合同协议书
- 星星火炬代代相传国旗下讲话稿
- 户外照明亮化工程劳动力安排计划
- 2022年青岛幼儿师范高等专科学校教师招聘考试试题及答案
- 非遗文化南音介绍
- 板式换热器对数平均温差计算公式
- 体育初中学生学情分析总结报告
- 幕墙工程安装施工施工管理人员配备及分工
- 《工程建设标准强制性条文电力工程部分2023年版》
- 中国历史地理(山东联盟)智慧树知到期末考试答案2024年
- (正式版)JBT 10618-2024 组合式电涌保护器(箱)
- 书法生职业生涯规划
评论
0/150
提交评论