zoukankan      html  css  js  c++  java
  • 读书笔记深入linux内核架构Chapter 2 part3

     进程调度

     

    clip_image001

    三个组件:调度器、调度器类、上下文切换。

     

    struct task_struct {

        ...

        int prio, static_prio, normal_prio;

        unsigned intrt_priority;

        struct list_head run_list;

        const struct sched_class *sched_class;

        struct sched_entity se; //调度器不限于调度进程,可以处理更大的实体(组调度)。因此要求调度器不直接处理进程,而是处理se.

      

        unsigned intpolicy;

        cpumask_t cpus_allowed//sched_setaffinity

        unsigned inttime_slice;

        ...

    }

     

     调度器类:

    struct sched_class {

        conststruct sched_class *next;

        void (*enqueue_task) (struct rq *rq, struct task_struct *p, int wakeup);

        void (*dequeue_task) (struct rq *rq, struct task_struct *p, int sleep);

        void (*yield_task) (struct rq *rq);

        void (*check_preempt_curr) (struct rq *rq, struct task_struct *p);

        struct task_struct * (*pick_next_task) (struct rq *rq);

        void (*put_prev_task) (struct rq *rq, struct task_struct *p);

        void (*set_curr_task) (struct rq *rq);

       

    //每次激活周期性调度器时,由周期性调度器调用task_tick

        void (*task_tick) (struct rq *rq, struct task_struct *p);

      

    //fork产生新进程时,用task_new通知调度器

        void (*task_new) (struct rq *rq, struct task_struct *p);

    };

     

     

     就绪队列:

    struct rq {

        unsignedlongnr_running;

        #define CPU_LOAD_IDX_MAX 5

        unsignedlongcpu_load[CPU_LOAD_IDX_MAX];

      ...

        struct load_weight load;

        struct cfs_rq cfs;      //嵌入的队列,管理CFS

        struct rt_rq rt;    //嵌入的队列,管理实时调度

        struct task_struct *curr, *idle;

        u64 clock;

      ...

    };

     

    定义一个数组runqueues[],每个CPU都有一个struct rq.

     

    static DEFINE_PER_CPU_SHARED_ALIGNED(struct rq, runqueues);

     

     

    调度实体:

    由于调度器可以操作比进程更一般的实体,因此需要一个适当的数据结构表示此类实体。

    struct sched_entity {

        struct load_weight load;    // for load-balancing

     

        struct rb_node run_node;

        unsignedinton_rq;

        u64exec_start;

        u64sum_exec_runtime;

        u64vruntime;

        u64prev_sum_exec_runtime;

        ...

    }

     

    优先级:

    clip_image003

     

    负荷:

    进程的优先级不仅由优先级指定,而且还要考虑保存在task_struct中的se.load的负荷权重。set_load_weight负责根据进程类型及其静态优先级计算负荷权重。

    负荷权重

    struct load_weight {

        unsignedlongweight, inv_weight;

    };

     

     

     

    周期性调度器

    按照一定频率自动调度(为省电可以关闭该调度器),在scheduler_tick中实现。

    该函数调用委托到的具体底层调度器。

     

    主调度器

    内核要将CPU分给另一个进程、从系统调用返回时检查到TIF_NEED_RESCHED时,会调用schedule函数。

    __sched前缀:用于标记可能调用schedule的函数(包括schedule函数自己),这些函数被放到sched.text代码段中,内核在显示栈转储时会忽略类似信息。

    asmlinkage void __sched schedule(void){

      … 

    prev->sched_class->put_prev_task(rq, prev); //通知调度器当前进程应被替换

    next = pick_next_task(rq, prev); //调度器选择下一个应该被执行的进程

    … 

    rq->curr = next;

    context_switch(rq, prev, next); //硬件级的进程切换

    … 

    }

     

     

    上下文切换

    static inline void context_switch(struct rq *rq, struct task_struct *prev, struct task_struct *next){

        …

        switch_mm(old_mm, mm, next);

        switch_to(prev, next, prev);

        barrier();

        finish_task_switch(this_rq(), prev);

    }

     

     

    switch_to之后的代码只有在当前进程再次被调度的时候,接着执行。

     

     

     

     

     

  • 相关阅读:
    DWR组件——基于远程过程调用实现Ajax
    JSTL学习笔记
    EL表达式学习笔记
    JavaScript学习笔记
    原生Ajax使用教程
    Response的返回内容类型
    Tomcat上文件的绝对路径访问笔记
    JSON语言规范与Java中两种解析工具基本使用
    Java生成XML文件与XML文件的写入
    编码问题笔记
  • 原文地址:https://www.cnblogs.com/apprentice89/p/2820743.html
Copyright © 2011-2022 走看看