linux 0.11 任务调度schedule

来源:互联网 发布:php程序源码 编辑:程序博客网 时间:2024/05/17 22:17

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);切换到要调度的任务。

 

0 0
原创粉丝点击