15.CPU调度——schedule

来源:互联网 发布:亚投行招聘 知乎 编辑:程序博客网 时间:2024/05/29 17:12

1.Linux 0.11 的调度函数 schedule

kernel/sched.c
schedule() 的目的是找到下一个任务 next,切换到下一个任务

/* * 'schedule()' is the scheduler function. This is GOOD CODE! There * probably won't be any reason to change this, as it should work well * in all circumstances (ie gives IO-bound processes good response etc). * The one thing you might take a look at is the signal-handler code here. * * NOTE!! Task 0 is the 'idle' task, which gets called when no other * tasks can run. It can not be killed, and it cannot sleep. The 'state' * information in task[0] is never used. *//* * 'schedule()'是调度函数。这是个很好的代码!没有任何理由对它进行修改,因为它可以在所有的 * 环境下工作(比如能够对IO-边界处理很好的响应等)。只有一件事值得留意,那就是这里的信号 * 处理代码。 * 注意!!任务0 是个闲置('idle')任务,只有当没有其它任务可以运行时才调用它。它不能被杀 * 死,也不能睡眠。任务0 中的状态信息'state'是从来不用的。 */void schedule (void){  int i, next, c;  struct task_struct **p;   // 任务结构指针的指针。  ……  while (1)    {      c = -1;      next = 0;      i = NR_TASKS;//从后往前遍历      p = &task[NR_TASKS];//将p设为task数组的最后一个地址      // 这段代码也是从任务数组的最后一个任务开始循环处理,比较每个就绪      // 状态任务的counter(任务运行时间的递减滴答计数)值,哪一个值大,运行时间还不长,next 就      // 指向哪个的任务号。      while (--i)      {        if (!*--p)          continue;        //Linux 0.11中,TASK_RUNNING是就绪态,counter是时间片        if ((*p)->state == TASK_RUNNING && (*p)->counter > c)          //判断是就绪态,并且 counter>-1,就给c和next赋值,遍历找到最大的counter          c = (*p)->counter, next = i;      }      // 如果比较得出有counter 值大于0 的结果,则退出while(1)的循环,执行任务切换。      // counter 最大的任务,优先级最高      if (c)        break;      // 否则c=0,说明就绪态的时间片都用完了,根据每个任务的优先权值,更新每一个任务的counter 值。      // counter 值的计算方式为counter = counter /2 + priority      for (p = &LAST_TASK; p > &FIRST_TASK; --p)        if (*p)        //执行过的任务 比初始任务 优先级高          (*p)->counter = ((*p)->counter >> 1) + (*p)->priority;    }  switch_to (next);     // 切换到任务号为next 的任务,并运行。}

2. counter的作用

2.1 时间片

do_timer 中 counter 减到0,就schedule

// shced.cvoid shed_init(void){    set_intr_gate(0x20, &timer_interrupt);}void _timer_interrupt:    ...    call do_timervoid do_timer(...){    if((--current->counter > 0))        return;    current-> counter = 0;//counter减到0,就schedule    schedule();}

2.2 优先级

优先级举例:
执行IO任务,程序没执行完时 counter > 0
当就绪队列counter都为0时 遍历队列,counter再加个初值,阻塞过的任务 比 新建的IO任务 优先级高
IO任务的counter变大,优先级提高,具有 前台进程的特征,可以优先执行
IO任务执行的时间越长,counter就越大,优先级越高

后台任务一直按照counter轮转,短任务优先执行完

void schedule (void){    ...    while (--i)    {      if (!*--p)        continue;      if ((*p)->state == TASK_RUNNING && (*p)->counter > c)        c = (*p)->counter, next = i;    }    ...    for (p = &LAST_TASK; p > &FIRST_TASK; --p)    if (*p)      (*p)->counter = ((*p)->counter >> 1) + (*p)->priority;    }}

2.3 counter保证了响应时间的界:

设 c(0) = p
c(t) = c(t - 1) / 2 + p

c(∞)=p + p/2 + p/4 + …… <= 2p
最长的时间片是2p

每个进程只用维护一个counter变量,简单高效
实际的schedule函数用了一个简单的算法折中了大多数任务的需求(CPU调度)

0 0
原创粉丝点击