在一个操作系统中,最重要的部分就是任务调度,linux的0.11版本的任务调度函数比较简单,所以学习任务调度的原理非常适用。

下面我们贴出来schedule函数的代码。

  12 /*3  *  'schedule()' is the scheduler function. This is GOOD CODE! There4  * probably won't be any reason to change this, as it should work well5  * in all circumstances (ie gives IO-bound processes good response etc).6  * The one thing you might take a look at is the signal-handler code here.7  *8  *   NOTE!!  Task 0 is the 'idle' task, which gets called when no other9  * tasks can run. It can not be killed, and it cannot sleep. The 'state'10  * information in task[0] is never used.11  */12 void schedule(void)13 {14     int i,next,c;15     struct task_struct ** p;1617 /* check alarm, wake up any interruptible tasks that have got a signal */1819     for(p = &LAST_TASK ; p > &FIRST_TASK ; --p)20         if (*p) {21             if ((*p)->alarm && (*p)->alarm < jiffies) {22                     (*p)->signal |= (1<<(SIGALRM-1));23                     (*p)->alarm = 0;24                 }25             if (((*p)->signal & ~(_BLOCKABLE & (*p)->blocked)) &&26             (*p)->state==TASK_INTERRUPTIBLE)27                 (*p)->state=TASK_RUNNING;28         }2930 /* this is the scheduler proper: */3132     while (1) {33         c = -1;34         next = 0;35         i = NR_TASKS;36         p = &task[NR_TASKS];37         while (--i) {38             if (!*--p)39                 continue;40             if ((*p)->state == TASK_RUNNING && (*p)->counter > c)41                 c = (*p)->counter, next = i;42         }43         if (c) break;44         for(p = &LAST_TASK ; p > &FIRST_TASK ; --p)45             if (*p)46                 (*p)->counter = ((*p)->counter >> 1) +47                         (*p)->priority;48     }49     switch_to(next);50 }

从代码注释中,我们可以看到linus本人对这段代码是比较推崇的。这段代码可以运行在任何边界,没有理由修改这段代码。有一点需要注意的是信号处理的代码。任务是一个空闲任务,只有在其他任务没有运行时该空闲任务才会被运行。空闲任务不能 被杀死,也不能睡眠。它的tcb即task[0].state,任务状态信息从来不用的。

接下来我们来分析代码。

14,15行定义了一些变量,要说明的是p 这是一个双重指针,双重针指向的类型是任务数据块.数据块里面存放着一个任务的所有信息。

19-28行的代码作用是进行的报警定时值,唤醒任何已经得到信号的可中断任务。

19行开始for循环从最后一个任务开始向前开始遍历所有的任务。

20行判断该任务是否存在,不存在则跳过。

21行判断如果设置过该任务的定时值,且该定时值已经过期则,在信号位图中置位SIGALRM,并清alarm.

要说明的一点是jiffies变量是系统开机开始算起的计时数  10ms/滴答

25.26行如果信号位图中除了被阻塞的信号外还有其它信号,并且任务处于可中断状态,则任务置位就绪态。 ~(_BLOCKABLE & (*p)->blocked)为忽略阻塞信号。

32到48行是调度程序中主要的部分。

先对几个变量进行说明。

(*p)->counter 表示 任务状态的剩余滴答计数。

i表示任务标号,p表示任务数组的地址。

c和next用来保存(*p)->counter和i

这里需要对i和p进行说明。初始

i = NR_TASKS;

p =&task[NR_TASKS]

这两个都是无效值,因为NR_TASKS,用宏定义为64,也就是最多运行64个任务。但因为有任务0,所以任务数只能从0-63.

所以在37,38行判断前对i和p都进行了前减减操作。

39行也是为了判断任务存在,不存在的任务跳过。

40和41行是为了找到当前所有任务中即处于就绪态,且剩余的滴答计时最多的任务。

43行如果找到当前所有任务中即处于就绪态,且剩余的滴答计时最多的任务。跳出循环到49行进行任务切换。

如果当前就绪的所有任务的剩余的滴答数都为0,则重新为所有任务都分配滴答数。

45行为跳过不存在的任务。

46.47行为任务重新分配滴答数。

(*p)->counter = ((*p)->counter >> 1) +  (*p)->priority;

算法为counter = counter/2 + priority

44到48行是为所有的任务都重新分配滴答数。因为之前40行判断的时候可能处于非就绪状态的任务滴答数可能不为0,所以本次分配要对那些在40行判断非就绪状态的任务的滴答数加上之前剩余的一半 再加上自己的优先级。

此时系统中就绪态的任务的滴答数已经重新分配,所以循环回32行,可以重新找到就绪态的最大滴答数的任务。

然后在43行通过break退出循环,执行任务切换。

linux0.11学习之schedule相关推荐

  1. main函数解析(一)——Linux-0.11 学习笔记(五)

    main()函数解析(一)--Linux-0.11 学习笔记(五) 经过了前面的各种铺垫,终于来到了main函数.这篇博客的任务是把init/main.c讲清楚.由于牵扯到很多的函数调用,要想一次就说 ...

  2. main 函数解析(二)—— Linux-0.11 学习笔记(六)

    main函数解析(二)--Linux-0.11 学习笔记(六) 4.6 blk_dev_init函数 void blk_dev_init(void) {int i;for (i=0 ; i<NR ...

  3. kernel_mktime() 详解 —— Linux-0.11 学习笔记(四)

    题目:kernel_mktime() 详解 -- Linux-0.11 学习笔记(四) 在init/main.c文件中,有一个函数static void time_init(void) 该函数读取 C ...

  4. setup.s 分析—— Linux-0.11 学习笔记(二)

    更新记录 版本 时间 修订内容 1.0 2018-4-14 增加了"获取显示模式"这一节,AL取值的表格 标题: setup.s 分析-- Linux-0.11 学习笔记(二) 老 ...

  5. Linux0.11学习研究

    Linux0.11 环境搭建: 我参考的是这个博客:http://blog.csdn.net/u014688145/article/details/50575588 下载的文件:点击打开链接http: ...

  6. linux0.11学习笔记-技术铺垫-简单AB任务切换程序(1)-实现一个简单的bootloader

    直接看代码,即使已经理解了代码,但是还是会有种没有学到手的感觉.真正的掌握来自实践,来自己动手做出来."简单AB任务切换程序"系列文章的目的是,在bochs下,实践出简单AB两个任 ...

  7. head.s 分析——Linux-0.11 学习笔记(三)

    题目:head.s 分析 head.s 程序在被编译生成目标文件后会与内核其他程序一起被链接成 system 模块,它位于 system 模块的最开始部分,这也就是为什么称其为"头部(hea ...

  8. linux0.11学习笔记-技术铺垫-简单AB任务切换程序(3)-调试手段和方法

    写底层代码,我们需要特别的手段去调试,去debug.本文针对几种应用场景,介绍几种手段. 1. 查看文件的二进制值 - hexdump命令 以文章(2)中的head程序为例子 ld head.o -m ...

  9. main() 函数解析(一)——Linux-0.11 剖析笔记(六)

    文章目录 1. 宏定义`_syscall0` 2. `setup.s`读取的参数 3. 读取CMOS实时时钟信息 3.1 `outb_p(value,port)` 3.2 `inb_p(port)` ...

最新文章

  1. 推荐一个 Java 实体映射工具 MapStruct
  2. 博客搭建攻略(三):创造收益
  3. VTK:PolyData之Outline
  4. Nginx中添加gzip_static支持
  5. Docker中拉取ActiveMQ镜像安装运行网页无法访问已解决
  6. duliu——思维+线段树
  7. Facebook又开两处AI实验室,在西雅图和匹兹堡招兵买马
  8. 压缩UI深度的代码实现
  9. 浅析C++开发工程师的薪资与发展
  10. Ubuntu、kubuntu、xUbuntu、lubuntu等版本区别及界面样式
  11. logstash安装 window版
  12. html中左三角怎么写,css3三角形怎么写?
  13. JavaScript学习笔记(25) JavaScript.then()这个方法是什么意思?
  14. html标签(段落标签,换行标签,文本格式化标签和局部标签)-小白学习中
  15. java 汉字转换为拼音
  16. lucas-kanade学习
  17. matlab课本作业答案,MATLAB 实用教程 课后习题答案
  18. win7 jdk install and config
  19. 用Github建立个人主页
  20. 转:你的领导激情在哪里?发现它并为之而奋斗

热门文章

  1. 在App Service 透过Html 产生PDF
  2. Nginx面试!java项目答辩问题及答案
  3. dubbo的后台管理以及监控中心
  4. excel教程自学网_Excel自学教程:办公室必备技能——Excel表格的打印技巧
  5. python回车和换行的区别_回车与换行的区别(转)
  6. vue 使用orgChart
  7. 初三开始学计算机能够获奖吗,【喜报】我校初三王泽远同学喜获清华大学自主招生资格...
  8. 屁精 apple-polisher
  9. 攻防世界web入门-xff_referer write up
  10. 关于Drools:kie引擎的rest接口调用学习笔记