引言

一般来说,我们将实时操作系统区分为软实时系统(soft real-time system)和硬实时系统(hard real-time system)。软实时系统不保证会调度关键实时进程,而只保证这类进程会优先于非关键进程。硬实时系统具有更严格的要求:一个任务应在它的截止期限之前完成,在截止期限之后完成与没有完成是一样的。

最小化延迟

从事件到事件得到服务的这段时间称为事件延迟。事件延迟有两种类型:

  • 中断延迟

    中断延迟是从CPU收到中断到中断程序开始的时间。当一个中断发生时,操作系统应先完成正在执行的指令,在确定发生中断的类型,然后应该保存当前进程的执行状态,再采用特定的中断服务程序(ISR)来处理中断。执行上面说的这些任务所需要的时间就是中断延迟。

  • 调度延迟

    调度程序从停止一个进程到启动另外一个进程所需的时间量称为调度延迟。提供实时任务立即访问CPU要求,实时操作系统最大限度的减少这种延迟。保持调度延迟尽可能低的最有效的技术就是提供抢占式内核。

优先权调度

我们知道实时系统最重要的功能就是能够保证实时进程的相应。所以实时系统的地调度程序应支持抢占的基于优先权的算法。比如window提供32个不同的优先级,优先级的值16-31,专门用于实时系统,在Linux、Solaris中也具有类似的优先级方案

注意:提供抢占式的、基于优先级的调度程序仅能够保证软实时功能。硬实时系统应该进一步保证实时任务应在截止期限内得到服务。

首先进行调度的程序是周期性的,也就是说这些程序定期需要CPU,一旦周期性的获得CPU,他们具有固定的处理时间t、CPU应处理的截止期限d、以及周期p,三者的关系应为:0≤\leq≤t≤\leq≤d≤\leq≤p。周期任务的速率是1p\frac {1}{p}p1​。这样调度程序就利用这些特性,根据进程的截止期限或速率要求分配优先级。

这种形式调度特点在于:进程可能应向调度器公布截止期限要求。然后使用一种称为准入控制算法的技术,调度程序做两件事:他承认进程,保证进程完成;如果不能保证任务在截止期限前得到完成,拒绝请求。

单调速率调度

单调速率调度算法采用抢占式的、静态优先级的策略,调度周期性任务。所有的周期性任务在进入系统时会分配一个优先级,其值与周期成反比,即:周期越短,优先级越高;周期越长,优先级越低。这种算法假定:对于每次CPUU执行,周期性进程的处理时间是相同的,也就是在每次进程获取CPU时,它的CPU执行长度相同的。

单调速率调度可认为是最优的,如果一组进程不能由此算法调度,他不能由任何其他分配静态优先级的算法来执行。

尽管单调速率调度是最优的,但是有一个限制:CPU的利用率是有限的,并步总是可能完全最大化CPU资源。调度N个进程的最坏情况下的CPU利用率为:

               N(21N2^{\frac {1}{N}}2N1​ - 1)

对于具有一个进程的资源,CPU的利用率是100%。但是当进程数量趋近无穷时,它大约接近69%;对于具有两个进程的系统,CPU利用率在83%左右。

最早截止期限有限优先调度

最早截止期限有限调度(EDF)调度根据截止期限动态的分配有限级。截止期限越早,优先级越高,截止期限越晚,优先级越低。根据EDF策略:当一个进程可运行时。它要要系统公布截止期限要求。优先级可能需要进行调整,以便反应新可运行进程的截止期限(对比单调速率调度,其优先级是固定的)。

EDF调度不要求进程应是周期的,也不要求进程的CPU执行的长度是固定的。唯一的要求是:进程在变成可运行时,应向系统宣布截止期限

比例分享调度

比例分享调度程序在所有应用之间分配了T股。如果一个应用程序接收N股的时间,那么确保了它将有NT\frac {N}{T}TN​的总的处理器时间。

例如假设总的T=100股要在三个进程A、B、C之间进行分配,A分配到50股,B分配到15股,C分配到20股,这种方案确保:A有50%的总的处理器时间,B有15%,C有20%.

比例分享调度程序采用准入控制策略,以便确保没个进程能够得到分配时间:只有客户请求的股数小于可用的股数时,才能允许客户进入。

POSIX 实时调度

POSIX标准也提供一个实时计算扩展,POSIX定义两种类型的实时线程调度:

  • SCHED_FIFO
  • SCHED_RR

SCHED_FIFO采用FIFO队列,按照先来先服务策略调度线程,不过在具有同等优先级的线程之间没有分时,所以位于FIFO队列前面的最高优先级的实时线程在得到CPU后会一直占有直到终止或堵塞。

SCHED_RR采用轮询策略,类似SCHED_FIFO,但是提供了在同等优先级的线程之间进行分时。

POSIX还提供一个额外的调度类型SCHED_OTHER,它的实现没有定义,并且取决于特定系统,因此在不同系统上的行为可能不同。

POSIX API提供两个函数,用来获取和设置调度策略:

pthread_attr_getsched_policy(pthread_attr_t *attr, int *policy)
pthread_attr_setsched_policy(pthread_attr_t *attr, int policy)

这两个函数第一个参数是线程属性集的指针。

第二个参数是:

  • 获得当前调度策略的整数的一个指针(pthread_attr_getsched_policy)
  • 一个整数(SCHED_FIFO、SCHED_RR、SCHED_OTHER,用于pthread_attr_setsched_policy)

如果发生错误,这两个函数会返回非零值。

#include <pthread.h>
#include <stdio.h>
#define NUM_THREADS 5 void *runner(void *param); int main(int argc, int *argv[]) {
int i, policy;
pthread_t tid[NUM_THREADS];
pthread_attr_t attr; pthread_attr_init(&attr); if(pthread_attr_getschedpolicy(&attr, &policy) != 0) { fprintf(stderr, "Unable to get policy.\n");
}
else {
if(policy == SCHED_OTHER) {
printf("SCHED_OTHER\n");
}
else if(policy == SCHED_RR) {
printf("SCHED_RR\n");
}
else if(policy == SCHED_FIFO) {
printf("SCHED_FIFO\n");
}
} if(pthread_attr_setschedpolicy(&attr, SCHED_FIFO) != 0) {
fprintf(stderr, "Unable to set policy\n");
} for(i = 0; i < NUM_THREADS; i++) {
pthread_create(&tid[i], &attr, runner, NULL);
} for(i = 0; i < NUM_THREADS; i++) {
pthread_join(tid[i], NULL);
}
} void *runner(void *param) { pthread_exit(0);
}

这个例子首先确定当前的调度策略,然后将调度算法设置成SCHED_FIFO。

OS之进程管理---实时CPU调度的更多相关文章

  1. Linux进程管理 (2)CFS调度器

    关键词: 目录: Linux进程管理 (1)进程的诞生 Linux进程管理 (2)CFS调度器 Linux进程管理 (3)SMP负载均衡 Linux进程管理 (4)HMP调度器 Linux进程管理 ( ...

  2. OS之进程管理---进程调度和多线程调度

    进程调度基本概念 多道程序的目标就是始终允许某个进程运行以最大化CPU利用率,多个进程通时存在于内存中,操作系统通过进程调度程序按特定的调度算法来调度就绪队列中的进程到CPU,从而最大限度的利用CPU ...

  3. OS之进程管理---多处理器调度

    引言 之前我们所学习的操作系统进程调度策略的前提条件是单处理器系统下的CPU调度程序.如果系统中存在多个CPU,那么负载分配就成为可能,但是相应的调度问题就会更加复杂. 多处理器调度方法 对于多处理器 ...

  4. Linux内核——进程管理之CFS调度器(基于版本4.x)

    <奔跑吧linux内核>3.2笔记,不足之处还望大家批评指正 建议阅读博文https://www.cnblogs.com/openix/p/3262217.html理解linux cfs调 ...

  5. Python::OS 模块 -- 进程管理

    os模块的简介参看 Python::OS 模块 -- 简介 os模块的文件相关操作参看 Python::OS 模块 -- 文件和目录操作 os模块的进程参数 Python::OS 模块 -- 进程参数 ...

  6. OS之进程管理---多线程模型和线程库(POSIX PTread)

    多线程简介 线程是CPU使用的基本单元,包括线程ID,程序计数器.寄存器组.各自的堆栈等,在相同线程组中,所有线程共享进程代码段,数据段和其他系统资源. 传统的的单线程模式是每一个进程只能单个控制线程 ...

  7. OS之进程管理 --- 死锁

    什么是死锁 在正常操作模式下,进程按如下顺序来使用资源: 申请:进程请求资源 使用:进程对资源进行操作 释放:进程释放资源 当一组进程中的每一个进程度在等待一个事件,而这事件只能有一组进程的另一个进程 ...

  8. OS之进程管理---孤儿进程和僵尸进程

    僵尸进程 当一个进程终止时,操作系统会释放其资源,不过它位于进程表中的条目还是在的,直到它的父进程调用wait():这是因为进程表中包含了进程的退出状态.当进程已经终止,但是其父进尚未调用wait() ...

  9. kernel笔记——内核编译与进程管理

    内核与操作系统 由于一些商业操作系统设计上的缺陷以及日益庞杂,“操作系统”的概念对很多人而言变得含糊不清.在进一步讨论Linux内核的话题前,我们先区分“内核”与“操作系统”这两个概念. 操作系统:指 ...

随机推荐

  1. jquery中innerWidth(),outerWidth(),outerWidth(true)和width()的区别

    jquery中innerWidth(),outerWidth(),outerWidth(true)和width()的区别 var a = 元素本身的宽度: width() = a: innerWidt ...

  2. const变量指针赋值给非const类型的指针运行结果

    在c++可以定义一个const变量,然后把变量的值赋给一个非const指针,可以通过指针来改变const变量的值吗?下面的截图给出了答案

  3. 简单的socket编程

    1.socket 服务器搭建 实例化socket服务器,循环获取请求 package com.orange.util; import java.io.IOException; import java. ...

  4. 2018.10.19 NOIP训练 变化的序列(线性dp)

    传送门 f[i][j]f[i][j]f[i][j]表示后iii个对答案贡献有jjj个a的方案数. 可以发现最后a,ba,ba,b的总个数一定是n∗(n−1)/2n*(n-1)/2n∗(n−1)/2 因 ...

  5. noexcept(c++11)

    1.概念 1)c++中的异常处理是在运行时而不是编译时检测的,为了实现运行时检测,编译器可能会创建额外的异常处理代码,然而这会妨碍程序优化 2)noexcept说明符:若修饰函数(紧跟在参数列表后面) ...

  6. jaxws.xsd

    示例: <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://ww ...

  7. Git 同步远程仓库

    在你经常使用的命令当中有一个git branch –a 用来查看所有的分支,包括本地和远程的.但是时间长了你会发现有些分支在远程其实早就被删除了,但是在你本地依然可以看见这些被删除的分支. 同步远程分 ...

  8. Codeforces801C Voltage Keepsake 2017-04-19 00:26 109人阅读 评论(0) 收藏

    C. Voltage Keepsake time limit per test 2 seconds memory limit per test 256 megabytes input standard ...

  9. eclipse 安装

    做一个项目,需要搭建环境.使用sql server 2005,tomcat,eclipse.过程真复杂,碰到些小问题,不过都解决了,还算顺利. win7下sql server 2005安装:http: ...

  10. Delphi Dll 动态调用例子(3)-仔细看一下

    http://blog.163.com/bxf_0011/blog/static/35420330200952075114318/ Delphi 动态链接库的动态和静态调用 为了让人能快速的理解 静态 ...