linux0.11进程调度,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<

(*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,blocked,alarm。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表示屏蔽信号。

alarm是alarm信号。

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

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

if (*p) {

if ((*p)->alarm&& (*p)->alarm< jiffies) {

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

你可能感兴趣的:(linux0.11进程调度)