概述
调度的主要内容有核心数据区的初始化,调度初始化,和进程调度,消息派发。
1:在核心数据区有几个全局配置表,他们的关系为:
M_atPCB:
| …….. | wTno | wProcType | …… |
|
|
|
|
|
|
|
|
|
|
M_atProcTypeIndexTab:
wPATIndex | wNameIndex |
|
|
|
|
M_atProcTypeTab:
ucIsuse | wProcType | wTno | ……. |
|
|
|
|
|
|
|
|
atProcNameItemTab:
wProcType | acName | ucPlatSuppot |
|
|
|
|
|
|
M_atPCB是PCB池的第一个PCB指针,所以M_atPCB加上PCB索引即可得到相应的PCB指针,即:M_atPCB+wPCBIndex;
定位到M_atProcTypeIndexTab是通过如下方法得到的:
wProcType = ( M_atPCB+wPCBIndex)->wProcType;
wPATIndex = (M_atProcTypeIndexTab+wProcType)->wPATIndex;
定位到M_atProcTypeTab:
tProcType = M_atProcTypeTab+ wPATIndex;
然后就可以通过进程类型tProcType访问进程的属性了。
2:根据进程配置表创建进程,进程配置表定义了进程的属性,最小最大实例数,为每类进程根据其最大实例数来创建进程控制块,每个进程控制块创建完毕放入空闲队列,待使用该控制块的时候可以从空闲队列取出,放入使用队列中。
3:进程堆栈和私有数据区:进程堆栈和私有数据区的大小是按页的大小分配的,所以堆栈大小和私有数据区大小必须是页的整数倍。进程的堆栈可以共享,如果进程堆栈是共享的,则为该类进程的实例分配一个进程堆栈大小的空间,否则为每个进程实例都分配空间。分别在进程堆栈和进程私有数据区增加一个保护页,防止内存越界。
4:调度初始化:调度初始化分三个部分的内容,包括注册cpu过载信息,注册字节序翻转函数,启动所有进程和所有任务。这里主要讲下进程和任务的启动。
1) 进程的启动:根据M_atProcTypeTab进程属性,为每一类进程根据其最小实例数来启动进程,如果当前进程的属性值ucIsuse为否,则不启动;首先从进程的空闲队列中获取一个进程控制块索引,然后定位到进程控制块指针,把该进程控制块从空闲队列中取出,放入使用队列中,然后为其创建一个异步普通消息,创建成功则放入ready队列中,否则从使用队列取出放入空闲队列中,直到所有的进程都创建完。
2) 任务的启动:该类任务包括调度任务,系统任务,驱动任务;首先为该任务创建一个邮箱,平台中任务使用的邮箱包括三种,一种是vxworks使用的邮箱,一种是linux使用的邮箱,另一种是windows下使用的自定义邮箱。然后启动该任务。由于调度任务配置表与调度任务TCB数组是一一对应,这部分比较简单,下面简要说下:
通过T_atScheTCB和Tno访问任务的TCB:
ptScheTCB=T_atScheTCB+Tno;
通过TCB获得就绪进程:
wHead=ptScheTCB->wReadyHead;
ptHeadPCB=M_atPCB+wHead;
通过TCB获得阻塞进程:
wHead=ptScheTCB->wBlockHead;
ptHeadPCB=M_atPCB+wHead;
5:进程调度,
任务首先判断其就绪队列是否为空,如果不空,则从就绪队列中取出就绪进程,否则从消息队列中取消息,进行消息派发。取出就绪进程之后,定位到该进程的消息头,如果该消息为远程调用,则调用远程过程,否则运行进程。
在运行进程的时候还要判断消息的类型,如果为异步消息,同步消息,或者定时器消息,则直接运行进程,如果为同步应答消息,则会恢复进程的调用,返回到进程上下文。
这里讲一下栈切换:栈切换分为正常的栈切换和非正常的栈切换。正常的栈切换是从任务栈切换到进程栈,等进程运行完毕之后再切换到任务栈,不需要保存进程栈的上下文。非正常的栈切换是从任务栈切换到进程栈,但是进程没有运行完毕,需要保存进程栈的上下文环境,待某一时刻继续运行进程。两者的主要区别是前者进程运行完毕,不需要保留进程栈的上下文,后者需要保留栈的上下文环境。
正常栈切换:首先把任务堆栈指针保存到进程控制块的wTaskSp中,运行进程。
非正常栈切换:把任务的堆栈指针保存到进程控制块wTaskSp中,运行进程,然后把进程的堆栈指针保存到进程控制块的wProcSp,导出任务的堆栈指针,运行任务。
正常的栈切换主要用在一下几种情况:
1) OSS_SaveCurMsg
2) OSS_SetNextState
3) OSS_SetDefaultNextState
4) DeleteSelf
非正常的栈切换主要用在以下几种情况
1) OSS_SendSynMsg发送同步消息
2) OSS_SendUrgentSynMsg发送紧急同步消息
3) OSS_CallRpclnCpu远程调用
4) OSS_DelayProcess进程延时
平台所使用的消息延时机制主要有以下几种:
1) taskDelay阻塞一个任务
2) vos_dealy平台封装的taskDelay
3) OSS_DelayProcess阻塞一个进程
6:消息派发:平台的消息派发主要分为任务内消息和任务间的消息。任务内消息直接挂在该进程的消息队列,如果该进程是因为等待消息而阻塞,则把该进程加入ready队列。如果是任务间消息派发,则把该消息放入任务的消息队列中。
7:同步消息的模型:同步消息的条件:同步消息不允许发送给本进程,具有堆栈共享的某类进程也不允许发送同步消息。如果进程A向进程B发送同步消息,则A发完同步消息之后,A进入阻塞状态,同时其阻塞原因为等待同步应答,这时候从进程空间非正常切换到任务空间,待进程B处理完该同步消息之后发送同步应答(如果是任务内,则不发送同步应答,直接把A加入ready队列,其解除阻塞原因为同步应答到),等A受到同步应答消息之后,再从A的任务恢复到进程A,这就是整个同步消息的模型。
最后
以上就是腼腆冬天为你收集整理的调度模块做了一个总结的全部内容,希望文章能够帮你解决调度模块做了一个总结所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复