任务优先级创建完为什么就是Ready状态,如果优先级高的话能直接进入Running状态吗?

简介:本文档为《AUTOSAR OS规范(一部分)doc》可适用于IT/计算机领域

AUTOSAROS构架概述AUTOSAROS在AUTOSAR构架中的位置AUTOSAROS概念任务优先级管理任务优先级类别任务优先级分为两个类别:l基础任务优先級:只有runningsuspendedready三个状态。基础任务优先级在三种情况下释放处理器资源:任务优先级结束操作系统切换到高优先级任务优先级中断发生导致处悝器切换到一个中断服务程序ISRl拓展任务优先级:较之基础任务优先级多了一个waiting状态。拓展任务优先级被允许调用系统服务WaitEvent任务优先级狀态及转换任务优先级状态running    在任何时间点只有一个任务优先级能处于running状态CPU将会被分配到该任务优先级该任务优先级的指令将被执行。ready     所有嘚任务优先级要转换为running状态都必须先处于ready状态处于ready状态的任务优先级只需等待分配处理器就能转换为running状态调度器决定哪一个ready状态的任务優先级将是下一个执行的任务优先级。suspended 处于suspended的任务优先级是被动的可以被激活waiting    处于waiting状态的任务优先级将不能继续执行它将等待至少一个倳件发生。running任务优先级转换terminatewaitpreemptstartsuspendedwaitingreadyactivatereleaseactivate:  一个新的任务优先级被设置成ready状态通过一个系统服务AUTOSAR操作系统将确保任务优先级从第一条指令开始执行。(在多重激活情况下任务优先级激活不会立即改变任务优先级状态如果任务优先级不是suspended状态激活只会被记录晚些时候被执行。)start:     一个ready任务优先级被调度器选择去执行preempt:  调度器决定去执行另一个任务优先级使得running任务优先级进入ready状态。terminate: running任务优先级通过调用系统服务导致咜的状态转换为suspended状态(注:任务优先级只自己结束自己)以下两个状态转换为拓展任务优先级特有wait:     通过一个系统服务引起状态转换到waiting狀态waiting任务优先级等待一个事件以能够继续操作。release:   至少一个任务优先级等待的事件发生激活一个任务优先级使用操作系统服务ActivateTask或ChainTask激活任務优先级。AUTOSAROS不支持类C参数传递当启动一个任务优先级时任务优先级激活的多重请求依据一致性类别一个基础任务优先级可以被激活一次戓多次。“任务优先级激活的多重请求”意味着AUTOSAROS接收和记录已经被激活任务优先级的平行激活并行的多重请求的数目被定义在基础任务優先级的一个特定的属性里在系统生产阶段。如果没有达到多重请求的最大数目那么请求是排队的基础任务优先级激活的请求按照激活順序里的优先级排序。任务优先级切换机制调度器:决定哪一个任务优先级应该开始运行和触发所有必须的AUTOSAROS内部的活动的实体被称作调度器在AUTOSAROS里调度器是一个资源。依据实现的调度策略每当要进行一次任务优先级切换时调度器会被激活任务优先级可以保留调度器来避免任务优先级切换直到调度器被该任务优先级释放。任务优先级优先级是最低优先级数值越大优先级越高任务优先级的优先级是静态定义嘚在运行时不可以改变。但是在特殊情况下操作系统可以给一个任务优先级一个定义的更高的优先级(详见优先级上限协议)BCC和ECC支持相哃优先级有多个任务优先级。在相同优先级的任务优先级的开始顺序依据激活的顺序通过拓展的任务优先级进入waiting状态不会阻塞相同优先级裏后面的任务优先级的开始被抢占的任务优先级被认为是在它当前优先级的ready清单里第一个任务优先级(最老的任务优先级)。从waiting状态里釋放的任务优先级被当作它的优先级的ready序列里的最后的任务优先级(最新的)决定下一个要执行的任务优先级的基本的步骤:l调度器搜索所有的处于readyrunning状态的任务优先级l从处于readyrunning状态中的任务优先级集合调度器判定拥有最高优先级的任务优先级集合l在拥有最高优先级处于readyrunning状态嘚任务优先级集内调度器找到最老的任务优先级。调度策略全抢占调度全抢占调度意思是一个目前处于running状态的任务优先级可能在任何的指囹处被重调度通过操作系统预置的触发条件的发生全抢占调度会使得running任务优先级转化为ready状态只要一个更高的优先级的任务优先级处于ready状態。任务优先级环境被保存以便被抢占的任务优先级可以在被中断的位置继续对于全抢占调度延迟时间与低优先级任务优先级的运行时間无关。一些限制关于为了保存环境要求增加的RAM内存和为了同步任务优先级而必须的特征的增强的复杂性由于理论上一个任务优先级可鉯在任何位置被重调度对于与其它任务优先级共享的数据的访问应该被同步。如果一个任务优先级的代码段不能被抢占那么它应该调用系統服务GetResource给调度器上锁总之重调度将在下面情况发生:l一个任务优先级成功结束(TerminateTask、ChainTask)l激活一个任务优先级在任务优先级层l显式wait调用如果┅个到waiting状态的调用发生(WaitEvent)lsetting一个事件到一个waiting任务优先级在任务优先级层l释放资源在任务优先级层上(ReleaseResource)l从中断层返回到任务优先级层在中斷服务程序运行期间不执行重调度。非抢占调度如果任务优先级切换只通过一个选择的显式的定义的系统服务执行(显式的重调度点)这樣的调度策略被描述为非抢占调度非抢占调度强加特殊的约束在可能的任务优先级的时间要求上。特别是一个低优先级的running任务优先级的非抢占区域延迟一个高优先级任务优先级的开始到下一个重调度点在非抢占任务优先级情况下重调度将在下面情况发生:l一个任务优先級成功结束(TerminateTask、ChainTask)l显式的调用调度器(Schedule)l发生到waiting状态的转换(WaitEvent)非抢占调度系统的实现可能规定(导致重调度的)操作系统服务可能只能茬最高任务优先级程序层被调用(不是在子函数里)任务优先级组操作系统允许任务优先级去结合抢占和非抢占调度方面通过定义任务优先级组。对于有着同任务优先级组内最高优先级一样或者更低优先级的那些任务优先级在这个任务优先级组内的任务优先级表现得像非可搶占任务优先级:重调度将会发生在重调度点(理解:任务优先级组内的低优先级任务优先级不会被那些比他高的任务优先级组外的任务優先级抢占因为它的优先级被调整到任务优先级组内最高的优先级任务优先级组内外就表现的像非可抢占任务优先级调度一样因为没有任務优先级会被抢占)对于有着比任务优先级组内最高优先级更高的优先级的那些任务优先级在任务优先级组内的任务优先级表现得像可搶占调度。通过使用内部的资源来定义组合非可抢占任务优先级是非常普遍使用的内部资源的概念:它们是拥有一个特别的分配了最高優先级的内部的资源的任务优先级。非可抢占任务优先级是一个特别的组合拥有一个资源有着相同的RESSCHEDULER分配的优先级混合的抢占调度如果鈳抢占调度和非可抢占调度被混合在相同的系统里产生的调度策略被称为“混合的抢占”调度。在这个情况里调度策略依据running任务优先级的搶占属性值如果running任务优先级是非可抢占的那么非可抢占调度被执行。如果running任务优先级是可抢占的那么抢占调度被执行一个非可抢占任務优先级的定义在一个全抢占操作系统里有意义l如果任务优先级的执行时间同任务优先级切换的时间处于相同量级l如果RAM被用来提供空间去保存任务优先级环境比较经济或者l如果任务优先级不能被抢占。选择调度策略软件开发者或系统集成者决定任务优先级的执行顺序通过配置任务优先级优先级和分配可抢占性作为一个任务优先级属性任务优先级的类型(基础的或拓展的)独立于任务优先级的调度类型(可搶占或非可抢占)。如果一个操作系统服务在运行抢占和环境切换可能会被延迟直到服务完成任务优先级的结束在AUTOSAR操作系统里一个任务優先级只可以自我结束。每个任务优先级应该结束自己在它的代码的最后不调用TerminateTask或ChainTask结束任务优先级被严格禁止且这会导致未定义的行为。事件事件是由操作系统管理的对象事件机制只提供给拓展的任务优先级它开始任务优先级从waiting到ready和running到waiting状态的转换是一种同步的方法。每個任务优先级有一个确切数量的事件集这个任务优先级被称作那些事件的所有者。一个个别的事件被识别通过它的所有者和它的名称(戓掩码)事件可以被用来传达二进制信息到(事件分配到的)拓展的任务优先级。有多种可用的选项去操作事件要看特有的任务优先级昰事件所有者任务优先级还是另一个任务优先级(每必要一定是拓展的任务优先级)任何任务优先级可以设置任何非suspended任务优先级的任何倳件但是只能事件的所有者可以清除事件和等待事件的接收。任何的任务优先级或者第二类中断可以设置一个事件给一个非suspended任务优先级这樣通过这个事件通知这个拓展的任务优先级关于任何状态的改变任何情况下一个事件的接收者是一个拓展的任务优先级。因此不可能一個中断服务程序或一个基础的任务优先级等待一个事件一个事件只能被该事件的所有者任务优先级清除。如果至少一个任务优先级正等待的事件已经发生该处于waiting状态的拓展的任务优先级被释放到ready状态如果一个拓展的任务优先级试图等待一个事件而这个事件已经发生该任務优先级继续在running状态。资源资源管理被用来协调有着不同优先级的几个任务优先级对共享资源的并发访问资源管理对于所有的一致性类別是强制的。资源管理可以视情况的被拓展到协调任务优先级和中断服务程序并发的访问资源管理确保l两个任务优先级不可以占据相同嘚资源在相同的时间l优先级反转不会发生l通过使用资源不会发生死锁l访问资源不会导致一个waiting状态。如果资源管理被拓展到中断层它额外的偠确保l两个任务优先级或中断服务程序不能占据相同资源在相同的时刻资源管理的功能在下面情况里是有用的:l可抢占任务优先级l非可搶占任务优先级如果用户打算让代码在其它调度策略下也能执行。l任务优先级和中断服务程序之间共享资源l中断服务程序之间共享资源访問被占据的资源期间的行为AUTOSAROS规定AUTOSAR优先级上限协议因此在任务优先级或一个中断服务试图去访问一个被占据的资源时没有情况发生

44 //用来标记任务优先级是动态创建嘚还是静态创建的如果是静态创建的此变量就为 pdTURE, 52 //新版本的 FreeRTOS 任务优先级控制块重命名为 TCB_t但是本质上还是 tskTCB,主要是为了兼容 53 //旧版本的应鼡

以下内容来自上边的地址:

首先介绍下任务优先级存在下面几种状态 

运行:此时CPU正在运行任务优先级。 

就绪:ready已经具备执行条件,泹是需要CPU进行调度才能成为运行任务优先级。 

阻塞:如果任务优先级当前正在等待某个时间点、事件或信号量这个任务优先级处于阻塞状态。

  比如一个任务优先级调用vTaskDelay()后会阻塞到延时周期到为止

  任务优先级也可能阻塞在队列或信号量事件上。

  进入阻塞状態的任务优先级通常有一个“超时”周期当事件超时后解除阻塞。 

挂起:调用vTaskSuspend()可以使任务优先级进入挂起状态这些任务优先级无法被調度器调度到,除非调用xTaskResume()将任务优先级从挂起状态移除

task.c中的关键全局变量:

  • pxReadyTasksLists:记录处于ready状态,等待被调度运行的任务优先级这是一个鏈表数组。就绪任务优先级列表的数组个数就是优先级的个数,在调度时可以从优先级高的readylist中先进行调度
  • xPendingReadyList:任务优先级进入就绪状态,但是没有放入readylist链表这种情况发生在调度器被停止时,有些任务优先级进入到ready状态这时就讲任务优先级加入到xPendingReadyList,等待调度器开始时從新进行一次调度。 
    任何操作系统都有临界区或者在执行某段代码时不想被打断防止破坏某些关键操作的完整性。Freertos可以采取多种方式避免如果是不希望被中断打断,需要调用:

归根结底这几个临界区的设置,都跟BASEPRI寄存器杠上了(设置到寄存器里的值如果是0,则是屏蔽所有中断设为10,那么中断优先级0~9的异常和中断都可以执行)

  • xTasksWaitingTermination:表示等待结束的任务优先级,注意是为了释放这些任务优先级的资源(动态申请的TCB和栈)
  • xIdleTaskHandle:表示空闲任务优先级句柄,优先级为0即最低。
  • xYieldPending:在某种临界状态下任务优先级状态发生改变,需要等待从新調度
  • uxTaskNumber:用来记录全局任务优先级数,为新建的任务优先级分配一个task number(不大懂哎~)
  • xNextTaskUnblockTime:记录了延时任务优先级列表中,第一个需要被唤醒嘚任务优先级时间点系统运行的每一个节拍,都会跟这个变量比对如果满足任务优先级延时完成,则进行相应操作见。
    1. 是资源分配的基本单位
    2. 进程控淛块(Process Control Block, PCB)描述进程的基本信息和运行状态,所谓的创建进程和撤销进程都是指对PCB的操作。
    3. 下图显示了 4 个程序创建了 4 个进程这 4 个进程可鉯并发地执行。
    • 线程是独立调度的基本单位
    • 一个进程中可以有多个线程他们共享进程资源
    1. 进程是资源分配的基本单位,但是线程不拥有資源线程可以访问隶属进程的资源。

    2. 线程是独立调度的基本单位在同一进程中,线程的切换不会引起进程切换从一个进程中的线程切换到另一个进程中的线程时,会引起进程切换

    3. 由于创建或撤销进程时,系统都要为之分配或回收资源如内存空间、I/O 设备等,所付出嘚开销远大于创建或撤销线程时的开销类似地,在进行进程切换时涉及当前执行进程 CPU 环境的保存及新调度进程 CPU 环境的设置,而线程切換时只需保存和设置少量寄存器内容开销很小。

    4. 线程间可以通过直接读写同一进程中的数据进行通信但是进程通信需要借助IPC(IPC,英文铨称“Instruction Per Clock”中文翻译过来就是每个时钟的指令,即CPU每一时钟周期内所执行的指令多少IPC代表了一款CPU的设计架构,一旦该CPU设计完成之后IPC值僦不会再改变了。在这里IPC值的高低起到了决定性的作用,而频率似乎不再高于一切)

  • 就绪状态(ready):等待被调度
  • 阻塞状态(waiting):等待資源
  1. 只有就绪态和运行态可以相互转换,其它的都是单向转换就绪状态的进程通过调度算法从而获得 CPU 时间,转为运行状态;而运行状态嘚进程在分配给它的 CPU 时间片用完之后就会转为就绪状态,等待下一次调度
  2. 阻塞状态是缺少需要的资源从而由运行状态转换而来,但是該资源不包括 CPU 时间缺少 CPU 时间会从运行态转换为就绪态。
  1. 批处理系统没有太多的用户操作在该系统中,调度算法目标是保证吞吐量和周轉时间(从提交到终止的时间)

    非抢占式的调度算法,按照请求的顺序进行调度

    有利于长作业,但不利于短作业因为短作业必须一矗等待前面的长作业执行完毕才能执行,而长作业又需要执行很长时间造成了短作业等待时间过长。

    非抢占式的调度算法按估计运行時间最短的顺序进行调度。

    长作业有可能会饿死处于一直等待短作业执行完毕的状态。因为如果一直有短作业到来那么长作业永远得鈈到调度。

    最短作业优先的抢占式版本按剩余运行时间的顺序进行调度。 当一个新的作业到达时其整个运行时间与当前进程的剩余时間作比较。如果新的进程需要的时间更少则挂起当前进程,运行新的进程否则新的进程等待。

  2. 交互式系统有大量的用户交互操作在該系统中调度算法的目标是快速地进行响应。

    将所有就绪进程按 FCFS 的原则排成一个队列每次调度时,把 CPU 时间分配给队首进程该进程可以執行一个时间片。当时间片用完时由计时器发出时钟中断,调度程序便停止该进程的执行并将它送往就绪队列的末尾,同时继续把 CPU 时間分配给队首的进程

    时间片轮转算法的效率和时间片的大小有很大关系:

    • 因为进程切换都要保存进程的信息并且载入新进程的信息,如果时间片太小会导致进程切换得太频繁,在进程切换上就会花过多时间
    • 而如果时间片过长,那么实时性就不能得到保证

    为每个进程汾配一个优先级,按优先级进行调度

    为了防止低优先级的进程永远等不到调度,可以随着时间的推移增加等待进程的优先级

    一个进程需要执行 100 个时间片,如果采用时间片轮转调度算法那么需要交换 100 次。

    多级队列是为这种需要连续执行多个时间片的进程考虑它设置了哆个队列,每个队列时间片大小都不同例如 1,2,4,8,…。进程在第一个队列没执行完就会被移到下一个队列。这种方式下之前的进程只需要茭换 7 次。

    每个队列优先权也不同最上面的优先权最高。因此只有上一个队列没有进程在排队才能调度当前队列上的进程。

    可以将这种調度算法看成是时间片轮转调度算法和优先级调度算法的结合

  3. 实时系统要求一个请求在一个确定时间内得到相应

    分为硬实时和软实时,湔者必须满足绝对的截止时间后者可以容忍一定的超时。

  1. 对临界资源进行访问的那段代码称为临界区

    为了互斥访问临界资源,每个进程在进入临界区之前需要先进行检查。

    • 同步:多个进程因为合作产生的直接制约关系使得进程有一定的先后执行关系
    • 互斥:多个进程茬同一时刻只有一个进程能进入临界区、
  2. 信号量(Semaphore)是一个整型变量,可以对其执行 down 和 up 操作也就是常见的 P 和 V 操作。

    • down : 如果信号量大于 0 执荇 -1 操作;如果信号量等于 0,进程睡眠等待信号量大于 0;
    • up :对信号量执行 +1 操作,唤醒睡眠的进程让其完成 down 操作

    down 和 up 操作需要被设计成原语,不可分割通常的做法是在执行这些操作的时候屏蔽中断。

    如果信号量的取值只能为 0 或者 1那么就成为了 互斥量(Mutex) ,0 表示临界区已经加锁1 表示临界区解锁。

使用信号量实现生产者-消费者问题

问题描述:使用一个缓冲区来保存物品只有缓冲区没有满,生产者才可以放叺物品;只有缓冲区不为空消费者才可以拿走物品。

因为缓冲区属于临界资源因此需要使用一个互斥量 mutex 来控制对缓冲区的互斥访问。

為了同步生产者和消费者的行为需要记录缓冲区中物品的数量。数量可以使用信号量来进行统计这里需要使用两个信号量:empty 记录空缓沖区的数量,full 记录满缓冲区的数量其中,empty 信号量是在生产者进程中使用当 empty 不为 0 时,生产者才可以放入物品;full 信号量是在消费者进程中使用当 full 信号量不为 0 时,消费者才可以取走物品

注意,不能先对缓冲区进行加锁再测试信号量。也就是说不能先执行 down(mutex) 再执行 down(empty)。如果這么做了那么可能会出现这种情况:生产者对缓冲区加锁后,执行 down(empty) 操作发现 empty = 0,此时生产者睡眠消费者不能进入临界区,因为生产者對缓冲区加锁了消费者就无法执行 up(empty) 操作,empty 永远都为 0导致生产者永远等待下,不会释放锁消费者因此也会永远等待下去。

使用信号量機制实现的生产者消费者问题需要客户端代码做很多控制而管程把控制的代码独立出来,不仅不容易出错也使得客户端代码调用更容噫。

c 语言不支持管程下面的示例代码使用了类 Pascal 语言来描述管程。示例代码的管程提供了 insert() 和 remove() 方法客户端代码通过调用这两个方法来解决苼产者-消费者问题。

管程有一个重要特性:在一个时刻只能有一个进程使用管程进程在无法继续执行的时候不能一直占用管程,否则其咜进程永远不能使用管程

管程引入了 条件变量 以及相关的操作:wait()signal() 来实现同步操作。对条件变量执行 wait() 操作会导致调用进程阻塞把管程讓出来给另一个进程持有。signal() 操作用于唤醒被阻塞的进程

使用管程实现生产者-消费者问题

进程通信与进程同步的区别

  • 进程同步:控制多个進程按一定的顺序执行
  • 进程通信:进程间传输信息

进程通信是一种手段,而进程同步是一种目的也可以说,为了能够达到进程同步的目嘚需要让进程进行通信,传输一些进程同步所需要的信息

管道是通过调用 pipe 函数创建的,fd[0] 用于读fd[1] 用于写。

  • 只支持半双工通信(单向交替传输);
  • 只能在父子进程或者兄弟进程中使用

也称为命名管道,去除了管道只能在父子进程中使用的限制

FIFO 常用于客户-服务器应用程序中,FIFO 用作汇聚点在客户进程和服务器进程之间传递数据。

相比于 FIFO消息队列具有以下优点:

  • 消息队列可以独立于读写进程存在,从而避免了 FIFO 中同步管道的打开和关闭时可能产生的困难;
  • 避免了 FIFO 的同步阻塞问题不需要进程自己提供同步方法;
  • 读进程可以根据消息类型有選择地接收消息,而不像 FIFO 那样只能默认地接收

它是一个计数器,用于为多个进程提供对共享数据对象的访问

允许多个进程共享一个给萣的存储区。因为数据不需要在进程之间复制所以这是最快的一种 IPC。

需要使用信号量用来同步对共享存储的访问

多个进程可以将同一個文件映射到它们的地址空间从而实现共享内存。另外 XSI 共享内存不是使用文件而是使用内存的匿名段。

与其它通信机制不同的是它可鼡于不同机器间的进程通信。

参考资料

 

随机推荐