参考的是ULK第三版,Linux2.6.11.12内核版本。
调度程序依靠几个函数来完成调度工作,其中最重要的第一个函数是scheduler_tick函数,主要步骤如下:
/** * 维持当前最新的time_slice计数器 * 每次时钟节拍到来时,scheduler_tick函数将被调用,以执行与调度相关的操作。 */ void scheduler_tick(void) { int cpu = smp_processor_id(); runqueue_t *rq = this_rq();//宏this_rq()产生本地CPU运行队列的地址 task_t *p = current; /** * 把转换为纳秒的TSC的当前值存入本地运行队列的timestamp_last_tick中。 * 这个时间戳由sched_clock获得。 */ rq->timestamp_last_tick = sched_clock(); /** * 检查当前进程是否是idle进程。swapper进程,就是0号进程 */ if (p == rq->idle) { /** * 检查运行队列中除了IDLE进程外,是否还有其他可运行进程。 * 如果有,就设置当前进程的TIF_NEED_SCHEDULED字段,以强迫进行调度。 */ if (wake_priority_sleeper(rq)) /** * 没有必要更新IDLE进程的时间片计数器. */ goto out; rebalance_tick(cpu, rq, SCHED_IDLE); /** * 没有必要更新IDLE进程的时间片计数器,所以此处直接返回。 */ return; } /** * 检查current->array是否指向本地运行队列的活动链表。 * 如果不是,说明进程已经过期但还没有被替换, * 设置TIF_NEED_SCHEDULED标志,以强制进行重新调度。并跳转 */ if (p->array != rq->active) { set_tsk_need_resched(p); goto out; } /** * 获得运行队列的自旋锁。 */ spin_lock(&rq->lock); //递减时间片 ... out_unlock: /** * 释放自旋锁。 */ spin_unlock(&rq->lock); out: /** * 调用rebalance_tick函数,该函数应该保证不同CPU的运行队列 * 包含数量基本相同的可运行进程。 */ rebalance_tick(cpu, rq, NOT_IDLE); }
这就是此函数所做的主要工作,总体思想。