当前位置:首页 > VxWorks kernal programmers guide
6.5.8
任务执行控制
Table 6-8列出的函数提供直接控制一个任务执行。
任务执行过程中,若出现一些重要错误,则要求重启任务。重启机制,taskRestart( ),用原来的创建参数重新创建一个任务。
延迟操作为任务提供固定休眠的一个简化机制。任务延迟通常用于轮询应用。如延迟一个任务半秒,无须考虑时钟频率。调用taskDelay( )如下:
taskDelay (sysClkRateGet ( ) / 2);
sysClkRateGet( )函数返回系统速率:ticks/s。取代taskDelay( ),你可以使用POSIX nanosleep( )函数指明具体的延迟。仅单位不同;延迟函数是一样的,取决于系统时钟。详细,
参考9.6 POSIX Clocks and Timers。
注明调用taskDelay( )从ready队列中删除调用任务。当任务再次准备好运行,位于对应优先级就绪队列最后。这个行为用于通过使用0 ticks延迟函数放弃CPU给其它对等优先级的任务。
taskDelay (NO_WAIT); /* allow other tasks of same priority to run */ 只有taskDelay( )函数可以使用0参数。nanosleep( )函数不可以。关于就绪队列更多信息,参考Scheduling and the Ready Queue。
注:ANSI和POSIX APIs相似。
系统时钟分辨率通常是60Hz(一秒钟60下)。这是一个时钟tick比较长的时间,可以是100Hz或120Hz。因此,因为周期延迟是有效轮询,你会考虑使用使用事件驱动的技术。
6.5.9 任务调度控制
任务在创建时被指派一个优先级(参考6.5.1 Task Creation and Activation)。在运行过程中,可以通过调用taskPrioritySet( )改变一个任务的优先级。动态改变优先级的功能允许应用跟踪实际操作流程的变化。小心使用taskPrioritySet( )函数改变一个任务的优先级,改变后任务位于对应优先级就绪队列最后。关于就绪对象相关信息,参考Scheduling and the Ready Queue。
Table 6-9列出了用于控制任务块的一组函数。
6.5.10 任务扩展:钩子函数
为了允许额外任务相关的工具增加到系统,VxWorks提供了钩子函数,允许当任务创建时,一个任务上下文切换时,或一个任务被删除时,增加的函数被触发。TCB中有空闲域来为一个任务的上下文应用扩展。这些钩子函数在Table 6-10列出;更多信息,参考taskHookLib相关API。
任务创建的钩子函数在创建任务的上下文中执行。任务创建钩子必须考虑钩子函数中创建的任何内核对象的所有权关系(如看门狗定时器,信号量等)。因为创建钩子函数在创建任务的上下文中执行,新任务的进程拥有新的内核对象。可能必须要指派这些对象的所有权给新的任务进程。这会防止当进程创建的任务中止时,不期望的对象被回收。
当使用任务切换钩子函数时,要意识到如下限制:
? 不要假设任何虚拟内存上下文为当前内存上下文,处理内核上下文(用ISRs)。 ? 不要依赖目前任务的识别或依赖这个信息触发任何函数,如taskIdSelf( )。
? 不要依赖taskIdVerify (pOldTcb)来确定是否为自我析构任务情况下删除执行的钩子。取而代之的是,删除钩子中其它状态信息当切换钩子时要被检测到(通过设置NULL指针)。
内核上下文中用户安装的切换钩子被调用,因此不能访问所有VxWorks设施。Table 6-11总结了一个任务切换钩子中可以调用的函数;通常任何不涉及内核调用的函数。
注:关于POSIX扩展信息,参考9. POSIX Facilities。
6.6 任务错误状态:errno
按照惯例,C库函数设置一个单一全局整数变量errno为一个正确的错误号,当函数遇到错误时。这个惯例指定为ANSI C 标准的一部分。
注:这一部分描述了VxWorks单处理器配置中errno的实现和用法。关于SMP的errno和其他全局变量的信息,参考24.17.8 SMP CPU-Specific Variables and Uniprocessor Global Variables,关于移植的信息,参考24.17 Migrating Code to VxWorks SMP。 6.6.1 errno的分层定义
VxWorks中,errno同时以两种方式定义。ANSI C标准,一个潜在称为errno的全局变量,可以通过主机开发工具使用名字展示。
然而,在errno.h文件中errno被定义为一个宏。这个定义整个VxWorks可见除了一个函数。这个宏被定义为一个返回全局变量地址的函数__errno( ),errno(你可能猜的到,这是一个单一函数,本身不使用errno宏定义)。这个策略产生一个有用的工具:因为__errno( )是一个函数,在调试时你可以设置断点,来确定产生错误的地方。
尽管如此,因为宏errno的结果是全局变量errno的地址,C程序可以用标准的方式设置errno值:
errno = someErrorNumber;
对于任何其它的errno实现,不要关注相同名称的局部变量值。
6.6.2 针对每个任务的一个独立errno值
VxWorks中,潜在全局errno是一个单一的预定义全局变量,可以被链接到VxWorks中的应用代码直接引用(或静态在主机上引用或在加载时动态使用)。
然而,在VxWorks多任务环境中errno很有用,每个任务必须查找自身版本的errno。因此,被保存,通过内核回复,作为每次一个上下文切换产生时每个任务上下文一部分。
同样,interrupt service routines (ISRs)查看自身的errno版本号。通过保存和恢复中断栈上的errno,作为内核自动提供的进入和退出中断代码的一部分(8.3.1 Connecting Routines to Interrupts)。
因此,不管VxWorks上下文,不用直接操作全局变量errno的情况下一个错误码可以保持和提交。
6.6.3 错误返回惯例
几乎所有的VxWorks函数都遵循一个规范,通过实际函数返回值来表示函数操作正确与否。很多函数仅返回OK (0)或ERROR (-1)。一些正常返回一个非负数的函数(如,open( )函数返回一个文件描述符)也返回ERROR表示一个错误。返回一个指针的函数,通常返回NULL(0)表示一个错误。大多数情况下,一个函数返回如一个错误表示也设置errno为特别的错误码。
全局变量errno从来不会被VxWorks函数清除。因此,它的值总表示上一次设置的错误状态。当一个VxWorks子函数在调用其他函数时得到一个错误提示,通常无须修改errno,返回自身的错误提示。因此,errno值在低层次函数中设置保持为错误类型的提示。
6.6.4 错误状态值指派
VxWorks errno值编码产生错误的模块,使用最重要的两个字节为独立错误计数。所有VxWorks模块数范围是1-500;一个0模块数errno值用于源码兼容性。
其它errno值(也就是说,所有的正值)提供给应用使用。
参考相关VxWorks API,获取定义和编码errno值规范的更多信息。
6.7 任务异常处理
程序代码或数据中的错误会导致硬件异常条件如非法指令,总线或地址错误,除数为0,等。VxWorks异常处理报关注这些异常(参考19. Error Detection and Reporting)。
任务可以通过信号工具关联它们的句柄来处理特定的硬件异常。若一个任务针对一个异常提供了一个信号回调,上面描述的默认异常回调是不会执行的。一个用户定义的信号回调在从重要错误中恢复时非常重要。通常,调用setjmp( )函数定义函数中的恢复点,在回调中调用longjmp( )函数来恢复上下文。注明longjmp( )恢复任务的信号屏蔽的状态。
信号也用于通知软件异常,还有硬件异常。在8.2 Signals描述,和sigLib中相关API。
6.8 共享代码和可重入性
7 任务间和进程间通讯
共分享92篇相关文档