JOS 轮转调度实现

来源:互联网 发布:科比季后赛平均数据 编辑:程序博客网 时间:2024/05/22 01:51

  JOS的轮转调度示意图:
  
这里写图片描述
  JOS的轮转调度思想比较简单,当env[i]进程来调用sched_yield()函数的时候,表示进程i要让出CPU了,此时,系统会从i开始,不停的往下寻找状态为runnable的进程,然后执行那个进程。如果遍历了所有的进程队列,发现没有进程满足运行条件,此时分两种情况,若原进程满足运行条件,即状态是runnable,则运行原进程,若原进程不满足运行条件,即原进程被阻塞或者被杀死,则调用 sched_halt(), 让CPU停止工作,直到下次时钟中断,再重新执行上面的过程。具体代码如下:
  

voidsched_yield(void){    struct Env *e = thiscpu->cpu_env;    int EnvID = 0;    int startID = 0;    int i=0;    bool firstEnv = true;    if(e != NULL){        EnvID =  e-envs;        if(e->env_status == ENV_RUNNING)            e->env_status = ENV_RUNNABLE;        startID = (EnvID+1) % (NENV-1);    }    for(i = startID; firstEnv || i != EnvID; i = (i+1)%(NENV) ){        if(envs[i].env_status == ENV_RUNNABLE){            env_run(&envs[i]);        }        firstEnv = false;    }    if(e )        env_run(e);    // sched_halt never returns    sched_halt();   }

  结合上面的代码看,轮转调度实现方法比较简单,唯一要注意的就是
  if(e->env_status == ENV_RUNNING)
    e->env_status = ENV_RUNNABLE;
  e表示的是CPU里调用轮转调度的进程,就是上图的进程env[i]。本来,我直接把e的状态改为了env_runnable,对于前面的所有的练习都是没有问题的。但是后面的primes和其他几个用户例子出了问题。回过头来,发现不能直接把进程的status改为可执行的。因为不止用户态的进程会调用轮转调度这个函数,在lab4的后面练习中,有些进程可能被阻塞或者进程被杀死了,此时,也是会调用轮转调度这个函数的。此时不加判断的直接把进程的状态改为runnable就会产生错误了。所以要给进程原状态做一个判断,进程状态是running的,也就是表示进程是因为时钟中断时间片用完了或者自愿放弃CPU的时候,才能将状态改为runnable.其他情况下,进程不会再被执行了。

0 0
原创粉丝点击