这里真是一个好地方。我刚接触linux,因此迫不及待的想知道一些问题,还望赵博士理解。
第一个问题,我想知道的是任务调度函数sched()在哪些情况下会被调用?我以前看过uCOS,它是这样的:
1、系统时钟中断处理中
2、创建任务的时候
3、任何改变任务状态的系统函数,如semTake(), semGive()
4、中断返回
不知道linux中怎么样?
第二个问题,听说linux的调度机制是non-preemptive的。我也看到在您的书中第22页提到“在内核态下运行的进程不能被其它进程抢占。”因此我觉得很迷惑,难道一个低优先级的进程不能被高优先级的进程剥夺么?并且在第79页看到您写道“当时钟中断过程判断出它运行的时间片已被用完时,就会在do_timer()中执行进程切换操作,该进程的CPU 使用权就会被不情愿地剥夺,让给别的进程使用。”我理解这里的别的进程应该就是高优先级并且就绪的进程。那么可以认为在时间片到达的时候高优先级的进程就会剥夺低优先级的进程。
另外中断处理结束的时候好象也进行了一次调度,这时候如果有高优先级的任务就绪,那么被中断的低优先级任务不是就被剥夺了么。
由此我发现自己对抢占式调度和非抢占式调度的概念并不清楚。您能解释解释这个问题么?
基本的情况下都一样。在创建任务时并不调用schedule(),而是仅设置任务为可运行状态。较详细的有以下一些地方:
1. 系统调用中判断时间片用完;
2. 系统调用中判断当前进程状态是否已经不处于RUNNING状态;
3. 进程调用exit();
4. 系统调用waitpid()并且flag没有WNOHANG标志,或子进程在ZOMBIE状态等;
5. tty写操作,但写队列已满;
6. 时钟中断;
7. 由于等待资源而自愿调用sleep_on();
8. 等待任何信号而调用pause()。
在内核态执行时不会被时钟中断过程强制切换掉,因为在时钟中断过程中有对是否运行在核心态的判断语句。至于在一个进程时间片用完后切换到什么进程,这完全由调度程序的算法设定。在本内核的调度程序中,schedule()会比较每个处于就绪状态任务的counter(时间片值)值,哪一个大,运行时间还不长,就基本选定切换到哪个任务。若所有时间片都为0(或相等?)就根据每个任务的优先权值更新每个任务的counter值,然后对所有任务重新比较。
可以看出这个内核中选择切换目标是首先根据时间片值,再根据优先权值。因此只是在大家都处于同一起跑线上时才根据优先权值选择下一个将要执行的任务,不存在高优先级进程剥夺低优先级任务运行的情况。
在中断处理结束时也是调用这个schedule(),因此处理过程完全一样。
请教任务调度的发起
感谢赵博士的讲解,本来一直有个疑问,感觉内核代码中对全局数据的访问很不保险似的,担心被中断打断后回来就乱了,现在清楚了哦。

