朋友们、伙计们,我们又见面了,本期来给大家解读一下有关Linux 2.6内核 调度队列和调度原理,如果看完之后对你有一定的启发,那么请留下你的三连,祝大家心想事成!
C 语 言 专 栏:C语言:从入门到精通
数据结构专栏:数据结构
个 人 主 页 :stackY、
C + + 专 栏 :C++
Linux 专 栏 :Linux
目录
1. 调度队列
一个CPU拥有一个runqueue
但是如果有多个CPU就要考虑进程个数的负载均衡问题(先不考虑这个)
2. 调度原理
2.1 优先级
先看runqueue,可以看到里面有一个queue[140],其实它完整的是
task_struct * queue[140]
是一个PCB指针数组,里面的每个位置都可以指向一个进程PCB!
实时优先级:0 ~ 99 (先不关心这个)
普通优先级:100 ~ 139(我们都是普通优先级)
那么普通优先级为什么是100 ~ 139呢?我们可以根据在进程优先级中每个进程的nice值结合在一起看;
Linux进程的默认优先级是80,nice值的取值范围在-20 ~ 19,所以我们Linux进程的优先级范围在60 ~ 99,一共是40个优先级,100 ~ 139也是40个优先级,所以在queue这个指针数组中的后40个位置就是我们Linux进程PCB优先级排队链接的地方!(数组下标就是优先级)
2.3 active指针和expired指针
如果我们细心观察可以发现:在runqueue中存在两个queue[140]数组,这是为什么呢?
进程是根据优先级进行调度的,如果在一个queue中,有一个优先级为60的PCB,还有一个80的PCB在排队,所以CPU在调度的时候,首先肯定会调度优先级为60的PCB,此时如果我们不断的添加更多的优先级为60的进程,就会一直调度60的PCB,那么优先级为80的PCB就会陷入进程饥饿,那么此时的CPU调度进程的公平性如何体现?
- 所以在runqueue中维护了两个queue[140],然后让active指针指向一个queue[140],再让expired指针指向一个queue[140];
- OS在调度的时候会优先调度active指针指向的queue,此时如果有新的进程创建,并不会直接插入到active指向的queue中,而是插入到expired指向的queue中进行优先级的排队;
- 当active指向的queue中的PCB调度完了,此时就将active和expired指向的内容进行交换,然后继续调度active指向的queue,此时就不会出现上面的进程饥饿问题。
2.4 活动队列和过期队列
- nr_active:总共有多少个被调度的进程PCB;
- active指针指向的queue[140]就叫做活动队列;
- expired指针指向的queue[140]就叫做活动队列。
2.5 bitmap(位图)
当我们在活动队列调度PCB的时候,是需要遍历找还是否存在可以调度的PCB的,粗暴一点的方法就是从前往后遍历的找,这种方式是比较费时间的,每次调度都要寻找,太麻烦了,所以就引入了一个新的结构:int bitmap[5]
根据比特位与字节的换算,bitmap中一共可以标志160个位置,我们都知道位图的查找时间复杂度是O(1),但是需要的就是消耗了一点空间,一种空间换时间的算法,主要的是保证了CPU调度PCB的效率。
2.6 总结
在系统当中查找一个最合适调度的进程的时间复杂度是一个常数,不随着进程增多而导致时间成本增加,我们称之为进程调度O(1)算法!
朋友们、伙计们,美好的时光总是短暂的,我们本期的的分享就到此结束,欲知后事如何,请听下回分解~,最后看完别忘了留下你们弥足珍贵的三连喔,感谢大家的支持!