Wince系统任务调度机制

目录

 

调度概述

一、线程优先级

二、可抢占

可抢占型内核

不可抢占型内核

三、时间片

四、wince中线程状态

五、wince的调度策略(怎么调度)

六、wince的调度时机(什么时候调度)

 

七、优先级反转

八、例子

例子1

例子2 

参考资料--WinCE6 Foundamentals

线程优先级划分


调度概述

调度是多任务操作系统中的一个基本概念。也是多任务操作系统内核必须提供的一种基本服务。调度的基本对象是任务(有些操作系统中也称为进程或线程),调度负责为系统中的任务分配当前CPU时间,决定当前CPU使用权由哪一个任务占用。调度大大简化了应用程序的设计,用户可以将一个应用分解成不同的任务,各任务的执行由多任务操作系统内核提供的调度服务管理。

Wince是一个基于优先级可抢占+时间片轮转算法调度的多任务操作系统。这是wince调度的基本机制。

Wince调度的基本单位是线程。现对wince调度基本机制中涉及到的几个概念作一些描述。

 

一、线程优先级

wince中的每个线程都有一个优先级。

Wince3.0之后优先级范围为0~255,其中0~247是实时优先级,248~255一般为应用程序的优先级。

一个线程创建时默认优先级是251。

创建线程时(CreateThread())没有办法直接设置优先级,但是用户可以动态提升某线程的优先级,有两个API可用SetThreadPriority和CeSetThreadPriority。前者可在248~255范围内调节,后者可提升至实时线程。

 

二、可抢占

基于任务优先级的操作系统内核有两种形式:可抢占和不可抢占型(有些地方也称可剥夺和不可剥夺型)

可抢占型内核

最高优先级任务一旦进入就绪状态,则立即获得CPU的使用权,当前运行任务的CPU使用权被立即剥夺,而不管当前任务是否已主动放弃CPU的使用权,比如时间片到、阻塞、挂起、睡眠等。

在可抢占型内核中,最高优先级任务由就绪态进入运行态的时间是可预知的,这使得系统中任务的响应时间得以最优化。在任务响应时间对系统很重要的场合,一般都使用可抢占内核的操作系统。Wince 、Uc/os-II、LINUX等操作系统都是可抢占内核。

使用可抢占式内核时,应用程序中不应直接调用不可重入函数。调用不可重入函数时,必须满足互斥条件。因为在优先级低任务和优先级高任务中可能会调用同一函数,如果该函数不为可重入函数且在低优先级任务调用该函数时,被高优先级任务抢占CPU的使用权。则该函数中的数据可能被破坏。

 

不可抢占型内核

每个任务都是主动放弃CPU的使用权,任务的CPU使用权是不可抢占的。当一个低优先级任务当前占有CPU时,一个高优先级任务进入了就绪状态,那么该高优先级任务必须等到占有CPU的低优先级任务主动放弃CPU使用权后,才能获得CPU使用权。

这种内核一般用于对系统响应时间不高,但任务的作业吞吐量大的操作系统内核。

 

 

三、时间片

时间片是操作系统分配给各个任务可占有CPU的时间。

如果任务在时间片用完后还没有结束,该任务被剥夺CPU的使用权并产生一次调度将CPU的占有权交给等待时间片最久的任务,而被剥夺时间片的任务将被排在就绪队列的末尾,等待下一次时间片分配。

上述是一个基本的时间片轮转算法,该算法通常只适用于相同优先级任务之间。时间片的长度是个头疼的问题。太短,则将导致过多的任务切换,浪费CPU时间;太长,则导致任务的响应时间变长,使系统变得迟钝。

在wince中时间片的默认长度为100ms。OEM可在内核初始化时改变该值的大小,分配给线程的时间片大小可用GetThreadQuantum()函数获得,也可以通过SetThreadQuantum()函数来设置当前线程的时间片大小。

 

四、wince中线程状态

Wince中线程的状态有6中,分别是:

1.运行(running:线程占有CPU ,正在执行。对于单核处理器,处于运行状态的线程永远只有一个;

2.就绪(ready:线程在该状态下具备了运行条件,但并没有处于运行状态。如果就绪的线程在调度时被选中,则占有CPU进入就绪状态。

处于就绪状态的线程可有多个。如果在处于就绪状态的线程中,最高优先级的线程的优先级比当前处于运行状态的线程优先级高,则立即产生一次抢占调度。该线程立即进入运行状态。调度的对象准确的说,应该是处于就绪状态的线程。 

3.挂起(suspended):如果在调用CreateThread()函数创建线程时指定了参数CREATE_SUSPENDED或调用SuspendThread()函数可导致线程挂起。

挂起的线程(挂起计数不为0)不能进入就绪状态,更不能占有处理器。每个挂起的线程都有一个挂起计数(线程的挂起计数由操作系统维护),调用SuspendThread(),挂起计数加1,调用ResumeThread(),挂起计数减1。当线程的挂起计数为0时进入就绪状态。

注:处于运行态的线程调用SuspendThread()函数,则产生一次调度使该线程进入挂起状态。如果SuspendThread()函数的参数hThread指定挂起的线程正处于就绪状态则该线程将进入挂起状态。

4.睡眠(sleeping:在线程中调用Sleep()函数可使线程进入睡眠状态,在该状态的线程不能进入就绪态,更不能占有处理器。Sleep()函数的参数dwMilliseconds 指定线程的睡眠时间,单位为ms。当线程的睡眠时间结束后,线程进入就绪状态。

Sleep( 0 )使当前进入放弃剩余的时间片,从运行态转入就绪态,等待下一次调度。

SleepINFINITE:使当前线程一直睡眠,直到线程被终止或唤醒;

5.阻塞(blocked线程等待的共享资源暂时无法获得时,那么该线程进入就绪状态。阻塞状态的线程不能进入就绪态,更不能占有处理器。当获得等待的共享资源后,线程进入就绪态。线程中对共享资源的等待是通过WaitForSingleObject()函数及WaitForMultipleObjects()函数来实现的。

6.终止(terminated):线程运行结束。一般线程是一个WHILE(1)结构,这意味着它本身永远也不会运行结束,要使一个线程终止必须调用ExitThread()函数。注意并不是关闭线程的句柄就会使线程终止。

 

各状态之间的转换如下:

 

 

 

  

五、wince的调度策略(怎么调度)

总的来说wince的调度策略可以总结为:基于优先级可抢占及时间片轮转算法调度策略。可以分两方面理解:

  1. 如果就绪队列中的最高优先级的线程优先级 > 当前占有CPU(运行状态)的线程优先级,则立即产生一次抢占调度,就绪队列中的最高优先级抢占CPU的使用权,进入运行状态;
  2. 如果就绪队列中的最高优先级的线程优先级 = 当前占有CPU(运行状态)的线程优先级,则执行时间片轮转调度算法:
    1. 运行状态的线程的时间片用完
    2. 运行状态的线程自身进入睡眠、阻塞或挂起状态

则立即产生一次调度,在就绪队列中等待时间最久的(也是在就绪队列最前的)线程获得CPU使用权,进入运行状态。同时用完时间片的线程排在同优先级就绪队列的最末位。如果一个线程的时间片被设为0,则表示该线程的时间片为无穷大。

 

 

六、wince的调度时机(什么时候调度)

操作系统将在以下时机产生一次调度:

  1. 抢占:当一个优先级高于处于运行状态线程的优先级的线程进入就绪状态时,则立即产生一次调度。
  2. tick周期:也就是时钟调度周期,在wince下默认为1ms。不论什么情况,操作系统总是每隔一个tick周期产生一次调度。
  3. 时间片到:系统分配给处于运行态线程的时间片到时,产生一次调度。
  4. 状态转换:处于运行态的线程使自身进入睡眠、挂起、阻塞状态,则产生一次调度。
  5. 中断:发生中断或中断处理返回时,产生一次调度。

 

七、优先级反转

如果低优先级占用了高优先级所需的资源,则在执行高优先级时,高优先级会被block,此时操作系统会进行优先级反转操作。

Priority inversion happens when a lower-level-priority thread blocks the execution of a higher-level-priority thread by holding the resource for which the higher-level priority thread waits.

 

wince支持一个层级的优先级提升,如果超过1个层级,则无法解决。

A one-level priority inversion denotes that only one thread’s priority is increased, which helps to resolve one-level blocking problems. If a lower-level-priority thread is blocked by a process with an even lower priority level, then one-level priority inversion will not be able to unblock the resource.

 

 

八、例子

例子1

线程1执行中,时间片到了之后,发生任务调度,由于线程1为最高优先级的就绪态,因此,线程1仍然继续执行

线程1执行中,被阻塞,进入阻塞态,发生任务调度,选择最高优先级就绪态的线程2执行

线程2执行中,时间片到了之后,发生任务调度。此时线程3也处于就绪态,并且线程3与线程2优先级一样,因此根据时间片轮转,运行线程3

线程3执行中,时间片到了之后,发生任务调度。切换到线程2运行

线程2执行完毕,主动进入阻塞,发生任务调度,切换到线程3

线程3执行完毕,主动进入阻塞,发生任务调度,切换到线程4

线程4执行中,时间片到了之后,发生任务调度。仍然运行线程4

线程4执行中,线程1获取到共享资源,从阻塞态切换到就绪态,由于线程1优先级高于正在运行的线程4,因此立即发生任务调度,切换到线程1运行

 

例子2

线程A获取了某共享资源

线程A被线程B抢占

线程B被线程C抢占

线程C也用到了线程A所占用的共享资源,因此高优先级的线程C被低优先级的线程A所阻塞

操作系统检测到这种异常后,临时将线程A优先级提高到与线程C一样

让线程A继续执行,直到线程C获取到该共享资源之后,再把线程A优先级恢复,切换到线程C执行

 

 

参考资料--WinCE6 Foundamentals

 

 

线程优先级划分

一般来说,最先需要决定的是要确定关键线程是否需要驱动程序。如果关键线程需要驱动程序才能正常工作,而将它的优先级设定为高于驱动程序的优先级,否则很难获得好的性能。总之,时间关键型应用程序需要放在“高于驱动程序类别的实时”类别中,优先级范围为 0-98。

 

 

细分如下:

 

 

实时线程优先级:CeSetThreadPriority

 

 

 

一般线程优先级:SetThreadPriority

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值