linux 0.11 任务调度schedule

Linux0.11 任务调度schedule

函数定义在sched.c当中,如下:

void schedule(void)
{
         int i,next,c;
         struct task_struct ** p;
 
/* check alarm, wake up any interruptible tasks that havegot a signal */
         for(p= &LAST_TASK ; p> &FIRST_TASK ; --p)
                   if (*p) {
                            if ((*p)->alarm &&(*p)->alarm< jiffies) {
                                               (*p)->signal|= (1<<(SIGALRM-1));
                                               (*p)->alarm =0;
                                     }
                            if (((*p)->signal& ~(_BLOCKABLE & (*p)->blocked))&&
                            (*p)->state==TASK_INTERRUPTIBLE)
                                     (*p)->state=TASK_RUNNING;
                   }
/* this is the scheduler proper: */
         while (1) {
                   c = -1;
                   next = 0;
                   i = NR_TASKS;
                   p = &task[NR_TASKS];
                   while (--i) {
                            if (!*--p)
                                     continue;
                            if ((*p)->state ==TASK_RUNNING && (*p)->counter> c)
                                     c = (*p)->counter, next =i;
                   }
                   if (c) break;
                   for(p = &LAST_TASK; p > &FIRST_TASK; --p)
                            if (*p)
                                     (*p)->counter= ((*p)->counter>> 1) +
                                                        (*p)->priority;
         }
         switch_to(next);
}

在linux0.11中,最多有64个任务同时存在,任务的相关信息存放一个数组里面,数组的结构(sched.h)如下:

struct task_struct {
/* these are hardcoded - don't touch */
         long state;        /* -1 unrunnable, 0 runnable, >0 stopped */
         long counter;
         long priority;
         long signal;
         struct sigaction sigaction[32];
         long blocked;   /* bitmap of masked signals */
/* various fields */
         int exit_code;
         unsigned long start_code,end_code,end_data,brk,start_stack;
         long pid,father,pgrp,session,leader;
         unsigned short uid,euid,suid;
         unsigned short gid,egid,sgid;
         long alarm;
         long utime,stime,cutime,cstime,start_time;
         unsigned short used_math;
/* file system info */
         int tty;               /* -1if no tty, so it must be signed */
         unsigned short umask;
         struct m_inode * pwd;
         struct m_inode * root;
         struct m_inode * executable;
         unsigned long close_on_exec;
         struct file * filp[NR_OPEN];
/* ldt for this task 0 - zero 1 - cs 2 - ds&ss */
         struct desc_struct ldt[3];
/* tss for this task */
         struct tss_struct tss;
};


在任务调度中,需要注意4个参数:state和signal,blockedalarm。State是任务的状态,有5中,在sched.h当中定义:

#define TASK_RUNNING 0//就绪,可运行状态,个人理解为正在运行或者等待运行的任务

#define TASK_INTERRUPTIBLE1     //可中断睡眠状态可有信号,wake_up唤醒,从sys_pause,sys_waitpid,interruptiable_sleep_on进入

#define TASK_UNINTERRUPTIBLE  2 //不可中断睡眠,只能由sleep_on()进入,wake_up函数唤醒

#define TASK_ZOMBIE              3 //僵死状态,不能再被调度

#define TASK_STOPPED            4 //暂停状态,0.11没有实现

Signal是任务接受到的信号图表,每一位代表一个信号,0表示没有信号,1表示有信号,blocked是任务当前屏蔽的信号图表,0表示没有屏蔽,1表示屏蔽信号。

alarmalarm信号。

任务调度是,从最后一个任务到第一个任务遍历,如果当前任务号对应的任务存在,则处理信号。先处理alarm信号,如果alarm信号存在,则在signal中置位,清楚alarm值,在这里,alarm值应该是从开机到定时器触发的滴答数,而jiffies是从开机到现在的滴答数,这样alarm < jiffies 表示的就是已经超过了定时器的触发时间。

如果还有其他未被屏蔽的信号存在,并且任务的状态为可中断睡眠状态,将进程设为就绪状态,等待调度执行。

if (*p) {
                            if ((*p)->alarm&& (*p)->alarm< jiffies) {
                                               (*p)->signal|= (1<<(SIGALRM-1));
                                               (*p)->alarm =0;
                                     }
                            if (((*p)->signal& ~(_BLOCKABLE & (*p)->blocked))&&
                            (*p)->state==TASK_INTERRUPTIBLE)
                                     (*p)->state=TASK_RUNNING;
                   }


下面的代码是任务的调度代码,主要是查询一个状态为就绪的,并且时间片最大的,且>0的任务执行,如果所有的任务时间片都为空了,重新分配所有任务的时间片,这里counter = counter /2 + priority,此时就绪状态的任务counter已经为0,但睡眠状态的任务不一定为0,所有重新分配时间片就是按照权值大小重新赋值:

while (1) {
                   c = -1;
                   next = 0;
                   i = NR_TASKS;// NR_TASKS==64;
                   p =&task[NR_TASKS];
                   while (--i) {        //从最后一个任务,63号任务开始,倒序遍历
                            if(!*--p)
                                     continue;
                            if((*p)->state == TASK_RUNNING && (*p)->counter > c)
                                     c= (*p)->counter, next = i;
                   }
                   if(c) break;
                   //在sched.h当中,#defineFIRST_TASK task[0]
//                                  #defineLAST_TASK task[NR_TASKS-1]
                   for(p= &LAST_TASK ; p > &FIRST_TASK ; --p)
                            if(*p)
                                     (*p)->counter= ((*p)->counter >> 1) + (*p)->priority;
         }


找到相应的任务后,执行switch_to(next);切换到要调度的任务。

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值