list_head结构如何用于在内核中进行调度

时间:2012-10-07 21:13:41

标签: linux linux-kernel kernel

我已经阅读了一些我可以知道的事情,而不是使用调度策略调度任务,我们最好安排一个具有调度策略的实体。优点是您可以使用相同的计划策略安排许多事情。因此,为两个调度策略(CFS和RT)定义了两个实体,即sched_entitysched_rt_entity。 CFS实体的代码是(来自v3.5.4)

struct sched_entity {
    struct load_weight  load;       /* for load-balancing */
    struct rb_node      run_node;
    struct list_head    group_node;
    unsigned int        on_rq;

    u64         exec_start;
    u64         sum_exec_runtime;
    u64         vruntime;
    u64         prev_sum_exec_runtime;

    u64         nr_migrations;


#ifdef CONFIG_SCHEDSTATS
    struct sched_statistics statistics;
#endif

#ifdef CONFIG_FAIR_GROUP_SCHED
    struct sched_entity *parent;
    /* rq on which this entity is (to be) queued: */
    struct cfs_rq       *cfs_rq;
    /* rq "owned" by this entity/group: */
    struct cfs_rq       *my_q;
#endif
};

和RT(实时)实体是

struct sched_rt_entity {
     struct list_head run_list;
     unsigned long timeout;
     unsigned int time_slice;

     struct sched_rt_entity *back;
     #ifdef CONFIG_RT_GROUP_SCHED
     struct sched_rt_entity  *parent;
     /* rq on which this entity is (to be) queued: */
     struct rt_rq            *rt_rq;
     /* rq "owned" by this entity/group: */
     struct rt_rq            *my_q;
     #endif
};

这两个都使用list_head

中定义的./include/linux/types.h结构
struct list_head {
     struct list_head *next, *prev;
};

老实说,我不明白将如何安排这样的事情。任何人都可以解释这是如何工作的。

P.S

此外,我真的很难理解数据成员名称的含义。任何人都可以建议一个良好的阅读理解内核结构,以便我可以轻松地弄清楚这些事情。我花费的大部分时间都浪费在搜索数据成员的含义上。

1 个答案:

答案 0 :(得分:2)

为了实现组调度,引入了调度实体,这样CFS(或RT调度程序)将为各个任务提供公平的CPU时间,同时为单个任务组提供合理的CPU时间。调度实体可以是任务或任务组。

struct list_head只是实现链表的Linux方式。在您发布的代码group_noderun_list中,您可以创建struct sched_entitystruct sched_rt_entity的列表。可以找到更多信息here

使用这些list_heads调度实体存储在某些与调度程序相关的数据结构中,例如cfs_rq.cfs_tasks如果实体是使用account_entity_enqueue()排队的任务。

始终可以在其源代码中找到Linux内核的最新文档。在这种情况下,您应该检查this目录,特别是this文件,其中描述了CFS。还有an explanation个任务组。

编辑: task_struct包含se类型的字段struct sched_entity。然后,使用sched_entity宏为container_of对象提供地址,可以检索task_struct对象的地址,请参阅task_of()。 (sched_entity对象的地址 - setask_struct的偏移量= task_struct对象的地址)这是我在前面提到的列表实现中常用的一种技巧答案。