今天学习了《linux内核设计与实现》的进程调度一章,总结一下自己的体会。
第一点:
进程调度主要分为I/O消耗型和处理器消耗型。从字面意思我们可以了解到他们的不同,一种主要是用于I/O操作,另一种是主要运行代码的过程。
第二点:
Linux对进程分配了优先级。
1. nice值,应该是静态的。-20到+19,默认是0,值越大优先级越小。
2. 另一种是实时的优先级,从0到99
第三点:
时间片,内核给每个运行的进程分配一个运行的时间,并不是一次让他全部运行完,而是给一个一定的时间,给用户的感觉就是可以多个程序并发的运行。
第四点:
进程抢占,Linux系统是抢占式的。当一个进态为TASK_RUNNING时,内核会检测他的优先级是否高于现在正在运行的进程。如果是则抢占。另外,当一个进程时间片用完时,为0,也会被抢占。一般I/O的时间片和优先级要高一些。
第五点:
调度算法.
每个处理器上都有一个可运行队列。其定义与:kernel/sched.c中。用于标示现在处理器的运行情况。具体结构书中有描述,不再重复。
每个运行队列有两个优先级数组,一个是活跃的,一个是过期的。运行的进程都在活跃的数组中,当其中的某些时间片用完后,内核把其下次运行的时间规定好后,放入过期数组中。当活跃数组空时,交换这两个数组,此时过期数组变成了活跃数组。
第六点:
schedule()用于进程切换。
第七点:
计算优先级和时间片。
一般根据进程睡眠时间确定是否是I/O处理型的。时间存放在task_struct中的sleep_avg中,当进程睡眠时这个值增加,当期运行时根据节拍逐渐减少。这样就可以确定他是睡眠时间多还是处理时间多。最大值为MAX_SLEEP_AVG。
优先级是可以实时的。内核可以在原来静态的基础上+/-5 ,其中niec值是基数。effective_prio()返回一个进程的动态优先级。
第八点:
睡眠和唤醒的步骤。见另外一篇文章。
第九点:
内核可以负载平衡。获取某个处理器中任务队列,根据某种测试,如果繁忙,可以把其中优先级高的放到其他处理器中执行。
第十点:
内核抢占时主要看其是否持有锁,如果持有则抢占应当注意,最好等没有锁时在抢占。即need_resched置位,并且preempt_count为0(没有锁)时。