嵌入式VxWorks学习总结报告 semMLibInit(), semCLibInit(), semOLibInit(), wdLibInit(), msgQLibInit(), qInit(), workQInit()
kernelInit()
初始化并启动内核。 (a)激活intLockLevelSet();
(b)从内存池顶部创建根堆栈和TCB;
(c)调用taskInit(),taskActivate(),用于usrRoot(); (d)调用usrRoot().
UsrRoot()
初始化I/O系统,驱动器,设备(在configAll.h和config.h中指定)
(a)调用sysClkConnect(),sysClkRateSet(),
iosInit(),[ttyDrv()];
(b)初始化excInit(),logInit(),sigInit(). (c)初始化管道,pipeDrv();
(d)stdioInit(),mathSoftInit()或mathHardInit() (e)wdbConfig():配置并初始化目标代理机
kernelLib.c
usrConfig.c
在大多数目标板的板级支持包中,VxWorks的入口点由两个函数:romInit()和romStart()来完成,而非sysInit()。具体基于ROM的VxWorks的初始化过程如下表所示: 函数
1.romInit()
2.romStart()
3.usrInit()
函数功能
(a)禁止中断; (b)保存启动类型; (c)硬件初始化; (d)调用romStart();
(a)将数据段从ROM拷贝到RAM,清内存; (b)将代码段从ROM拷贝到RAM,有必要的话解压
缩; (c)调用usrInit();
初始化程序
如果相应的配置文件被定义,对应函数被调用
所在文件
romInit.s
bootInit.c
usrConfig.c
3
嵌入式VxWorks学习总结报告
4.usrKernelInit()
5.kernelInit()
6.usrRoot()
7.Application routine
初始化并启动内核
初始化I/O系统,驱动器,创建设备
应用程序代码
Application source file
usrConfig.c
kernelLib.c
usrKernel.c
2.2.3 任务调度
目标板加电启动成功后,有如下几个任务已开始运行。他们就是VxWorks的系统任务。
(1)根任务:tUsrRoot
内核首先执行根任务tUsrRoot,其入口点为文件config/all/usrConfig.c中的usrRoot()函数,它负责初始化VxWorks工具,并创建注册、异常处理、网络通信任务和tRlogind等任务。一般来说,在所有的初始化工作完成后,根任务tUsrRoot被删除。
(2)注册任务:tLogTask
注册任务tLogTask被VxWorks模块用于传送不需I/O操作的系统消息。 (3)异常处理任务:tExcTask
异常处理任务tExcTask有最高优先级,它负责系统的异常情况出错处理,不能被悬置、删除或是改变其优先级。
(4)网络通信任务:tNetTask
网络通信任务tNetTask负责系统级任务的网络通信。 (5)目标代理任务:tWdbTask
如果目标代理程序运行在任务模式,目标代理任务tWdbTask被创建,用来响应主机目标服务器的请求。
实时系统的一个任务可有多种状态,其中最基本的状态有四种:
就绪态:任务只等待系统分配CPU资源;
悬置态:任务需等待某些不可利用的资源而被阻塞;
休眠态:如果系统不需要某一个任务工作,这个任务处于休眠状态; 延迟态:任务被延迟时所处状态;
当系统函数对某一任务进行操作时,任务从一种状态迁移到另一状态。处于任一状态的任务都可被删除。VxWorks内核的任务管理提供了动态创建、删除和控制任务的功能,具体实现通过如下一些系统调用:
taskSpawn()
创建(产生并激活)新任务
4
嵌入式VxWorks学习总结报告 taskInit() taskName()
初始化一个新任务 激活一个已初始化的任务 由任务ID号得到任务名 由任务名得到任务ID号 获得任务的优先级 检查任务是否被悬置 检查任务是否准备运行
taskActivate()
taskNameToId() taskPriorityGet() taskIsSuspended() taskIsReady() taskTcb() taskDelete() taskSafe()
得到一个任务控制块的指针
中止指定任务并自由内存(仅任务堆栈和控制块) 保护被调用任务
悬置一个任务 恢复一个任务 重启一个任务 延迟一个任务
taskSuspend() taskResume() taskRestart() taskDelay()
最高优先级任务正执行悬 置 态就 绪 态延 迟 态休 眠 态taskInit()
状态迁移
调用
semTake()/msgQReceive()
taskDelay() taskSuspend()
semGive()/msgQSend() taskSuspend() expired delay taskSuspend() taskResume() taskResume()
就绪态 ----> 悬置态 就绪态 ----> 延迟态 就绪态 ----> 休眠态 悬置态 ----> 就绪态 悬置态 ----> 休眠态 延迟态 ----> 就绪态 延迟态 ----> 休眠态 休眠态 ----> 就绪态 休眠态 ----> 悬置态 休眠态 ----> 延迟态
taskResume()/taskActivate()
5
嵌入式VxWorks学习总结报告 多任务调度须采用一种调度算法来分配CPU给就绪态任务。Wind内核采用基于优先级的抢占式调度法作为它的缺省策略,同时它也提供了轮转调度法。
基于优先级的抢占式调度,它具有很多优点。这种调度方法为每个任务指定不同的优先级。没有处于悬置或休眠态的最高优先级任务将一直运行下去。当更高优先级的任务由就绪态进入运行时,系统内核立即保存当前任务的上下文,切换到更高优先级的任务。
Wind内核划分优先级为256 级(0~255)。优先级0为最高优先级,优先级255为最低。当任务被创建时,系统根据给定值分配任务优先级。然而,优先级也可以是动态的,它们能在系统运行时被用户使用系统调用taskPrioritySet()来加以改变,但不能在运行时被操作系统所改变。
高优先级低t1时 间 注:表示抢占表示任务完成t1t2t3t2
轮转调度法分配给处于就绪态的每个同优先级的任务一个相同的执行时间片。时间片的长度可由系统调用KernelTimeSlice()通过输入参数值来指定。很明显,每个任务都有一运行时间计数器,任务运行时每一时间滴答加1。一个任务用完时间片之后,就进行任务切换,停止执行当前运行的任务,将它放入队列尾部,对运行时间计数器置零,并开始执行就绪队列中的下一个任务。当运行任务被更高优先级的任务抢占时,此任务的运行时间计数器被保存,直到该任务下次运行时。
高优t4先时间片级低t1t2t3t1t2t2t3时 间注:表示抢占,表示任务完成。
2.2.4 信号量
信号量VxWorks信号量是提供任务间通信、同步和互斥的最优选择,提
6
嵌入式VxWorks学习总结报告 供任务间最快速的通信。也是提供任务间同步和互斥的主要手段。VxWorks提供3种信号量来解决不同的问题。
二进制最快的最常用的信号量,可用于同步或互斥。互斥为了解决内在的互斥问题、优先级继承、删除安全和递归等情况而最优化的特殊的二进制信号量。计数器类似于二进制信号量,但是随信号量释放的次数改变而改变。
(1)二进制信号量
二进制信号量能够满足任务间的互斥和同步,需要的系统开销最小。二进制信号量可以看成一个标志,对应资源是可用还是不可用。当一个任务调用semTake ()请求一个信号量时,如果此时信号量可用,信号量会被清零,并且任务立即继续执行;如果信号量不可用,任务会被阻塞来等待信号量。
当一个任务调用semGive ()释放一个二进制信号量时。如果信号量已经可用,释放信号量不会产生任何影响;如果信号量不可用并且没有任务等待使用该信号量,信号量只是被简单地置为可用;如果信号量不可用并且有一个或多个任务等待该信号量,最高优先级的任务被解阻塞,信号量仍为不可用。
当两个以上的任务共享使用同一块内存缓冲区或同一个I/O设备之类的资源时,可能会发生竞争状态。二进制信号量可以通过对共享资源上锁,实现高效的互斥访问,不象禁止中断或禁止抢占,二进制信号量将互斥仅仅限于对与之联系的资源的访问,并且比禁止中断和禁止抢占提供更精确的互斥粒度。使用时创建用于保护资源的二进制信号量,初始时信号量可用。
当任务需要访问这个资源时,首先取得这个信号量,所有其它想要访问这个资源的任务将被阻塞。当任务完成了对该资源的访问时,释放该信号量,允许其他任务使用该资源。因此所有对一个需要互斥访问资源的操作由semTake ()和semGive ()对一起来实现:
semTake(semMutex,WAIT FOREVER) /*临界区,某一时刻仅被一个任务访问*/ semGive (semMutex)
信号量另一种通常的用法是用于任务间的同步机制。在这种情况下,信号量代表一个任务所等待的条件或事件。最初,信号量是不可用的。一个任务或中断处理程序释放该信号量来通知这个事件的发生。等待该信号量的任务将被阻塞直到事件发生、该信号量可用。一旦被解阻塞,任务就执行恰当的事件处理程序。信号量在任务同步中的应用对于将中断服务程序从冗长的事件处理中解放出来以缩短中断响应时间是很有用的。
(2)互斥信号量
互斥信号量是一种特殊的二进制信号量,用于解决具有内在的互斥问题:优先级继承、删除安全和对资源的递归访问等情况。
7