美文网首页
day13 sched调度程序

day13 sched调度程序

作者: 柯基是只dog | 来源:发表于2018-12-12 17:52 被阅读0次

func schedule

首先看下代码,逻辑其实不复杂,有个地方值得注意,调度前会遍历所有的进程,扫描他的alarm是否设置,并和滴答数比较,如果超过则给进程的alarm喜欢置位。然后遍历所有进程,如果有收到信号并且没屏蔽该信号,且进程的状态是可中断状态,则把进程的状态置位running,也就是说当我们的进程收到了信号之后该进程如果不是明确的不可中断状态,就会进入被调度的队列中。

void schedule (void)
{
    int i, next, c;
    struct task_struct **p; // 任务结构指针的指针。

/* 检测alarm(进程的报警定时值),唤醒任何已得到信号的可中断任务 */

// 从任务数组中最后一个任务开始检测alarm。
    for (p = &LAST_TASK; p > &FIRST_TASK; --p)
        if (*p)
        {
// 如果任务的alarm 时间已经过期(alarm<jiffies),则在信号位图中置SIGALRM 信号,然后清alarm。
// jiffies 是系统从开机开始算起的滴答数(10ms/滴答)。定义在sched.h 第139 行。
            if ((*p)->alarm && (*p)->alarm < jiffies)
            {
                (*p)->signal |= (1 << (SIGALRM - 1));
                (*p)->alarm = 0;
            }
// 如果信号位图中除被阻塞的信号外还有其它信号,并且任务处于可中断状态,则置任务为就绪状态。
// 其中'~(_BLOCKABLE & (*p)->blocked)'用于忽略被阻塞的信号,但SIGKILL 和SIGSTOP 不能被阻塞。
            if (((*p)->signal & ~(_BLOCKABLE & (*p)->blocked)) &&
                    (*p)->state == TASK_INTERRUPTIBLE)
                (*p)->state = TASK_RUNNING; //置为就绪(可执行)状态。
        }

  /* 这里是调度程序的主要部分 */

    while (1)
    {
        c = -1;
        next = 0;
        i = NR_TASKS;
        p = &task[NR_TASKS];
// 这段代码也是从任务数组的最后一个任务开始循环处理,并跳过不含任务的数组槽。比较每个就绪
// 状态任务的counter(任务运行时间的递减滴答计数)值,哪一个值大,运行时间还不长,next 就
// 指向哪个的任务号。
        while (--i)
        {
            if (!*--p)
                continue;
            if ((*p)->state == TASK_RUNNING && (*p)->counter > c)
                c = (*p)->counter, next = i;
        }
      // 如果比较得出有counter 值大于0 的结果,则退出124 行开始的循环,执行任务切换(141 行)。
        if (c)
            break;
      // 否则就根据每个任务的优先权值,更新每一个任务的counter 值,然后回到125 行重新比较。
      // counter 值的计算方式为counter = counter /2 + priority。[右边counter=0??]
        for (p = &LAST_TASK; p > &FIRST_TASK; --p)
            if (*p)
                (*p)->counter = ((*p)->counter >> 1) + (*p)->priority;
    }
    switch_to (next);       // 切换到任务号为next 的任务,并运行之。
}

sleep_on函数

明确的睡眠一个进程并且置状态为不可中断的,这里面有个tmp很有意思,tmp是局部变量,是保存在栈上的,然后用二级指针把等待的进程改为自己,而原来位置的等待进程则放到了tmp变量当中。然后把自己状态设置为不可中断,最后执行调度。当执行到调度后的代码的时候,说明该进程是被别的进程明确唤醒了,这时候去检查tmp也就是之前那个被等待的进程,如果存在则把它的状态设置正常。

void sleep_on (struct task_struct **p)
{
    struct task_struct *tmp;

    // 若指针无效,则退出。(指针所指的对象可以是NULL,但指针本身不会为0)。
    if (!p)
        return;
    if (current == &(init_task.task))   // 如果当前任务是任务0,则死机(impossible!)。
        panic ("task[0] trying to sleep");
    tmp = *p;           // 让tmp 指向已经在等待队列上的任务(如果有的话)。
    *p = current;           // 将睡眠队列头的等待指针指向当前任务。
    current->state = TASK_UNINTERRUPTIBLE;  // 将当前任务置为不可中断的等待状态。
    schedule ();            // 重新调度。
// 只有当这个等待任务被唤醒时,调度程序才又返回到这里,则表示进程已被明确地唤醒。
// 既然大家都在等待同样的资源,那么在资源可用时,就有必要唤醒所有等待该资源的进程。该函数
// 嵌套调用,也会嵌套唤醒所有等待该资源的进程。然后系统会根据这些进程的优先条件,重新调度
// 应该由哪个进程首先使用资源。也即让这些进程竞争上岗。
    if (tmp)            // 若还存在等待的任务,则也将其置为就绪状态(唤醒)。
        tmp->state = 0;
}

相关文章

  • day13 sched调度程序

    func schedule 首先看下代码,逻辑其实不复杂,有个地方值得注意,调度前会遍历所有的进程,扫描他的ala...

  • 设置Linux进程的优先级

    Linux内核的三种调度策略: SCHED_OTHER 分时调度策略, SCHED_FIFO实时调度策略,先到先服...

  • sched模块学习

    sched模块实现了一个时间调度程序,该调度程序可以通过单线程执行来处理按照时间尺度进行调度的事件。 通过调用sc...

  • Python标准库sched模块介绍

    sched——通用时间调度器 sched模块实现了一个通用事件调度器,在调度器类使用一个延迟函数等待特定的时间,执...

  • Linux 进程调度

    Linux的调度策略区分实时进程和普通进程,实时进程的调度策略是SCHED_FIFO和SCHED_RR,普通的,非...

  • Linux内核架构

    1.五大子系统 A) 进程调度 SCHED 3种类型的进程: SCHED_OTHERS SCHED_FIFO SC...

  • Hadoop调度器

    1.Hadoop调度器分为三类:FIFO、Capacity Scheduler(容量调度器)和Fair Sched...

  • pod 调度亲和性

    关于pod调度https://www.centos.bz/2017/07/kubernetes-pod-sched...

  • linux内核的三种调度方法

    linux内核的三种调度方法:1,SCHED_OTHER 分时调度策略(曾经使用了cpu最少的进程将会得到优先调度...

  • Laravel 自定义命令及任务调度

    自定义命令 任务调度 添加调度器 这个 Cron 会每分钟执行一次 Laravel 的命令行调度器。当 sched...

网友评论

      本文标题:day13 sched调度程序

      本文链接:https://www.haomeiwen.com/subject/dbuphqtx.html