Vxworks学习(四)_内核
声明本学习记录为笔者的学习记录笔记,其中大量借鉴了多本已出版书籍与网络资料,并会在文章末尾注明出处,同时笔者无虚拟机镜像。
本文参与于《VxWorks高级程序设计》-李方敏 进行整理。
一、实时内核
1.1 实时
实时表示控制系统能够计时处理系统中发生的要求控制的外部事件。
实时操作系统==性能评价指标: ==
- 中断延迟时间
- 任务切换时间
- 系统响应时间
实时操作系统必须满足的条件:
- 可抢占的内核
- 可抢占的优先级调度
- 中断优先级
- 中断可嵌套
- 系统服务的优先级由请求该服务的任务的优先级确定
- 优先级保护(优先级翻转保护)
- 前述实时操作系统性能评价指标具有固定上界;
Wind内核采用单一实时地址空间,任务切换开销非常低。
1.2 微内核
从内核功能和结构特点来看,具有整体式内核、层次式内核、微内核三种不同形式。
嵌入式操作系统大多采用微内核结构,具有以下优点:
- 统一的接口,在用户态和核心态之间无需进程识别;可伸缩性好,易于扩充,能适应硬件更新和应用变化;
- 可移植性好,操作系统要移植到不同的硬件平台上,只需修改微内核中极少代码即可;
- 实时性好,内核响应速度快,可以方便地支持实时处理;
- 安全可靠性高,微内核将安全性作为系统内部特性来进行设计,对外仅使用沙梁应用编程接口;
- 适合分布式计算环境。内核为进程传递消息的方式天然适合RPC这一计算模式。
为了提高微内核效率,有两种实现方式:受保护的虚地址空间模式和无保护的单一地址空间模式。
前者优势在于任务独立运行,可靠性高。
VxWorks 的 wind微内核采取单一实地址空间模式,所有任务在同一地址空间运行,不区分核心态和用户态。其优势在于:
- 任务切换时不需要进行虚拟地址空间切换;
- 任务间可以直接共享变量,不需要通过内核在不同的地址空间复制数据;
- 系统调用时不需要在核心态和用户态之间切换,相当于直接的函数调用。
1.3 任务调度
1.3.1 优先级调度
**不可抢占式调度: **需任务主动退出。
**抢占式调度: **注重实时响应。
Round-Robin调度
优先级翻转问题
task1 优先级: 1
task2 优先级: 2
task3 优先级: 3
task1与task3访问共享资源;
Begin: task1尝试访问资源,发现此时task3正在访问,因此task1被阻塞,等待task3释放共享资源,此时若task2申请CPU调度,则task3被抢占,由于task3无法继续执行继而无法释放共享内存,则task1持续被阻塞。此时的现象就是一个中优先级的任务可以被频繁调度,而低优先级和高优先级的任务被阻塞。
解决办法:优先级继承协议, 优先级天花板。
1.4 任务属性
Vx特点:
- 任务和内核具有相同权限,都能执行处理器所支持的全部指令
- 所有任务共享同一实地址空间
1.4.1 任务控制块
系统调度器使用TCB来管理任务调度功能。
TCB的一个重要内容就是任务上下文,代表了任务运行状态。
上写文切换两种情况:
- 同步上下文切换,引起的原因是当前运行的任务执行下列操作:(1)进行阻塞、延迟、挂起的调用;(2)使更高优先级任务就绪而发生优先级抢占;(3)降低自身优先级或者退出;
- 异步上下文切换,通常由ISR使更高优先级任务就绪引起。异步上下文切换比同步上下文切换需要更多时间。
调度程序开销主要取决于保存和恢复.上下文需要复制的寄存器数,要求该过程非常快。
1.4.2 钩子函数
VxWorks 允许任务创建“钩子函数”,安装钩子函数后,在规定事件发生时内核自动调用。具体来说有3类钩子函数:
(1)任务创建钩子:在任务被创建时调用;
(2)任务调度钩子:在任务被调度时调用;
(3)任务删除钩子:在任务被删除时调用,任务“删除”包括以任何方式调用函数taskDelete()、taskDeleteForce()和exit()引起的系统动作。
可以指定多个钩子函数,VxWorks确保钩子函数具有一致的调用顺序。当多个钩子函数之间存在某种依赖时,如下两点就显得很重要:
- 任务创建钩子函数和任务调度钩子函数按照其安装的顺序调用;
- 任务删除钩子函数按照与其安装顺序相反的顺序调用。
#include "taskHookLib.h"
STATUS taskCreateHookAdd (FUNCPTR createHook) ;
STATUS taskCreateHookDelete (FUNCPTR createHook);
STATUS taskDeleteHookAdd (FUNCPTR deleteHook) ;
STATUS taskDeleteHookDelete (FUNCPTR deleteHook) ;
1.4.3 任务状态
实时系统的一个任务可有多种状态,其中最基本的状态有5种:
- 运行——一任务获得CPU运行;
- 就绪——任务只等待系统分配 CPU资源;
- 阻塞——PENDED,因任务需等待某些不可利用的资源而被阻塞;
- 挂起——SUSPENDED,如果系统不需要某一个任务工作,则这个任务处于挂起状态。调度程序忽略该状态下的任务,但是对于任务接收信号,解除阻塞,延迟时间计数等没有影响;
- 延迟——DELAYED,任务被延迟时所处状态。
1.5 内核功能接口
Vx Works内核功能接口包含在多个库中:
- taskLib VxWorks任务管理:任务创建、删除、运行状态控制等;
- kernelLib VxWorks 内核:内核初始化,系统调度策略选择;
- semLib VxWorks信号量:提供二进制,互斥,计数信号量的管理;
- tickLib VxWorks系统时钟管理;
- wdLib VxWorks看门狗管理:看门狗的创建、启动、撤销和删除等。
1.5.1 任务控制
任务挂起与解除
#include "taskLib.h"
STATUS tasksuspend ( int tid ) ; /*挂起任务*/
STATUS taskResume ( int tid ) ;/*解除任务挂起*/
==注意: ==任务挂起时,要注意不要使系统陷入死锁,要防止任务获得了某个互斥访问的系统资源后被挂起。
任务互斥
VxWorks提供多种互斥机制:
- “测试-锁”vxTas( )
- 任务锁定taskLock( )
- 锁中断intLock( )
- 信号量semTake( )
任务重启
#include "taskLib.h"
STATUS taskRestart(int tid);
1.6 多任务与函数重入
代码重入性为“多线程安全性”;
允许在任一点存在多个运行实例的函数为第一类可重入函数(完全可重入)
除此以外的其他可重入函数称为第二类可重入函数
任务变量来实现函数重入
任务变量:就是任务上下文中记录的一个4字节数值,可以将其看成指向一个全局变量的指针。每次任务被调入处理器时,系统根据该指针自动从任务上下文装入全局变量的值;相应地,任务被调出处理器时,系统根据该指针自动将全局变量的值保存到任务上下文。
#inc1ude "taskvarLib.h"
STATUS taskvaradd (int tid, int *pvar);·/*定义新任务变量*/
STATUS taskvarDelete (int tid, int *pVar);/*删除任务变量*/
STATUS taskvarset (int tid, int *pvar,int value);/*设置任务变量值*/
int taskvarGet (int tid, int *pvar) ;/*取任务变量的值*/
int taskvarInfo (int tid,TASK_VAR varList [] ,int maxVars);/ *任务变量列表*/