scheduler 怎样得到 next task_struct

2024-06-03 16:18

本文主要是介绍scheduler 怎样得到 next task_struct,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

/**/

__schedule 调用函数pick_next_task从rq中得到一个task

/*
 * Pick up the highest-prio task:
 */
static inline struct task_struct *
pick_next_task(struct rq *rq)
{
    const struct sched_class *class;
    struct task_struct *p;

    /*
     * Optimization: we know that if all tasks are in
     * the fair class we can call that function directly:
     */
    if (likely(rq->nr_running == rq->cfs.h_nr_running)) {
        p = fair_sched_class.pick_next_task(rq);
        if (likely(p))
            return p;
    }

    for_each_class(class) {
        p = class->pick_next_task(rq);
        if (p)
            return p;
    }

    BUG(); /* the idle class will always have a runnable task */
}

#define sched_class_highest (&stop_sched_class)
#define for_each_class(class) \
   for (class = sched_class_highest; class; class = class->next)
sched_class的next成员指向下一个class,形成一个单向list
由list command得到所有的class.
crash> sym stop_sched_class
c0454ee8 (R) stop_sched_class
crash> list sched_class.next c0454ee8
c0454ee8
c0454e80
c0454e24
c0454dc8
crash> sym c0454ee8 c0454e80 c0454e24 c0454dc8
c0454ee8 (R) stop_sched_class
c0454e80 (R) rt_sched_class
c0454e24 (R) fair_sched_class
c0454dc8 (R) idle_sched_class

crash> list sched_class.next -s sched_class.pick_next_task c0454ee8
c0454ee8
  pick_next_task = 0xc0055850 <pick_next_task_stop>
c0454e80
  pick_next_task = 0xc0054b4c <pick_next_task_rt>
c0454e24
  pick_next_task = 0xc0050e4c <pick_next_task_fair>
c0454dc8
  pick_next_task = 0xc004fe08 <pick_next_task_idle
>

各sched_class是怎样得到next_task的?

idle:直接得到

static struct task_struct *pick_next_task_idle(struct rq *rq)
{
    schedstat_inc(rq, sched_goidle);
    calc_load_account_idle(rq);
    return rq->idle;
}

fair class:通过红黑树

static struct task_struct *pick_next_task_fair(struct rq *rq)
{
    struct task_struct *p;
    struct cfs_rq *cfs_rq = &rq->cfs;
    struct sched_entity *se;

    if (!cfs_rq->nr_running)
        return NULL;

    do {
        se = pick_next_entity(cfs_rq);
        set_next_entity(cfs_rq, se);
    } while (cfs_rq);

    p = task_of(se);

    return p;
}

pick_next_entity -> __pick_first_entity -> {struct rb_node *left = cfs_rq->rb_leftmost;}
cfs:这里才用到rb_node

rt:

pick_next_task_rt:
使用的是位图bitmap

/*
 * Priority of a process goes from 0..MAX_PRIO-1, valid RT
 * priority is 0..MAX_RT_PRIO-1, and SCHED_NORMAL/SCHED_BATCH
 * tasks are in the range MAX_RT_PRIO..MAX_PRIO-1. Priority
 * values are inverted: lower p->prio value means higher priority.
 *
 * The MAX_USER_RT_PRIO value allows the actual maximum
 * RT priority to be separate from the value exported to
 * user-space.  This allows kernel threads to set their
 * priority to a value higher than any user task. Note:
 * MAX_RT_PRIO must not be smaller than MAX_USER_RT_PRIO.
 */

#define MAX_USER_RT_PRIO    100
#define MAX_RT_PRIO        MAX_USER_RT_PRIO

#define MAX_PRIO        (MAX_RT_PRIO + 40)
#define DEFAULT_PRIO        (MAX_RT_PRIO + 20)

/*
 * This is the priority-queue data structure of the RT scheduling class:
 */
struct rt_prio_array {
    DECLARE_BITMAP(bitmap, MAX_RT_PRIO+1); /* include 1 bit for delimiter */
    struct list_head queue[MAX_RT_PRIO];
};
并不是没有优先级都对应一个 queue, [0, 100]的优先级才有

进程的 sched_class 成员是何时赋值的?

创建进程时或设置优先级时
1.
void sched_set_stop_task(int cpu, struct task_struct *stop)
    -> stop->sched_class = &stop_sched_class;

2./*设置优先级时*/
void rt_mutex_setprio(struct task_struct *p, int prio)
    ->     if (rt_prio(prio))
        p->sched_class = &rt_sched_class;
3.
void sched_fork(struct task_struct *p)
    ->     if (!rt_prio(p->prio))
        p->sched_class = &fair_sched_class;

4.
void __cpuinit init_idle(struct task_struct *idle, int cpu)
    idle->sched_class = &idle_sched_class;

与进程调度有关的数据结构

crash> rt_rq -o

struct rt_rq {
    [0] struct rt_prio_array active;
  [816] unsigned long rt_nr_running;
        struct {
            int curr;
            int next;
  [820] } highest_prio;
  [828] unsigned long rt_nr_migratory;
  [832] unsigned long rt_nr_total;
  [836] int overloaded;
  [840] struct plist_head pushable_tasks;
  [848] int rt_throttled;
  [856] u64 rt_time;
  [864] u64 rt_runtime;
  [872] raw_spinlock_t rt_runtime_lock;
}
SIZE: 880

SIZE: 880
其中的rt_prio_array占了880字节中的816字节。
crash> rt_prio_array
struct rt_prio_array {
    unsigned long bitmap[4];
    struct list_head queue[100];
}
SIZE: 816

crash> cfs_rq

struct cfs_rq {
    struct load_weight load;
    unsigned long nr_running;
    unsigned long h_nr_running;
    u64 exec_clock;
    u64 min_vruntime;
    u64 min_vruntime_copy;
    struct rb_root tasks_timeline;
    struct rb_node *rb_leftmost;
    struct sched_entity *curr;
    struct sched_entity *next;
    struct sched_entity *last;
    struct sched_entity *skip;
    unsigned int nr_spread_over;
}
SIZE: 72

crash> struct rq -o

struct rq {
     [0] raw_spinlock_t lock;
     [4] unsigned long nr_running;
     [8] unsigned long cpu_load[5];
    [28] unsigned long last_load_update_tick;
    [32] u64 nohz_stamp;
    [40] unsigned long nohz_flags;
    [44] int skip_clock_update;
    [48] struct load_weight load;
    [56] unsigned long nr_load_updates;
    [64] u64 nr_switches;
    [72] struct cfs_rq cfs;
   [144] struct rt_rq rt;
  [1024] unsigned long nr_uninterruptible;
  [1028] struct task_struct *curr;
  [1032] struct task_struct *idle;
  [1036] struct task_struct *stop;
  [1040] unsigned long next_balance;
  [1044] struct mm_struct *prev_mm;
  [1048] u64 clock;
  [1056] u64 clock_task;
  [1064] atomic_t nr_iowait;
  [1068] struct root_domain *rd;
  [1072] struct sched_domain *sd;
  [1076] unsigned long cpu_power;
  [1080] unsigned char idle_balance;
  [1084] int post_schedule;
  [1088] int active_balance;
  [1092] int push_cpu;
  [1096] struct cpu_stop_work active_balance_work;
  [1116] int cpu;
  [1120] int online;
  [1124] struct list_head cfs_tasks;
  [1136] u64 rt_avg;
  [1144] u64 age_stamp;
  [1152] u64 idle_stamp;
  [1160] u64 avg_idle;
  [1168] unsigned long calc_load_update;
  [1172] long calc_load_active;
  [1176] struct llist_head wake_list;
}
SIZE: 1184

crash> task_struct -o

struct task_struct {
    [0] volatile long state;
    [4] void *stack;
    [8] atomic_t usage;
   [12] unsigned int flags;
   [16] unsigned int ptrace;
   [20] struct llist_node wake_entry;
   [24] int on_cpu;
   [28] int on_rq;
   [32] int prio;
   [36] int static_prio;
   [40] int normal_prio;
   [44] unsigned int rt_priority;
   [48] const struct sched_class *sched_class;
   [56] struct sched_entity se;
  [128] struct sched_rt_entity rt;
  [152] unsigned char fpu_counter;
  [156] unsigned int policy;
  [160] cpumask_t cpus_allowed;
  [164] struct list_head tasks;
  [172] struct plist_node pushable_tasks;
  [192] struct mm_struct *mm;
  [196] struct mm_struct *active_mm;
  [200] unsigned int brk_randomized : 1;
  [204] struct task_rss_stat rss_stat;
  [220] int exit_state;
  [224] int exit_code;
  [228] int exit_signal;
  [232] int pdeath_signal;
  [236] unsigned int jobctl;
  [240] unsigned int personality;
  [244] unsigned int did_exec : 1;
  [244] unsigned int in_execve : 1;
  [244] unsigned int in_iowait : 1;
  [244] unsigned int sched_reset_on_fork : 1;
  [244] unsigned int sched_contributes_to_load : 1;
  [244] unsigned int irq_thread : 1;
  [248] pid_t pid;
  [252] pid_t tgid;
  [256] struct task_struct *real_parent;
  [260] struct task_struct *parent;
  [264] struct list_head children;
  [272] struct list_head sibling;
  [280] struct task_struct *group_leader;
  [284] struct list_head ptraced;
  [292] struct list_head ptrace_entry;
  [300] struct pid_link pids[3];
  [336] struct list_head thread_group;
  [344] struct completion *vfork_done;
  [348] int *set_child_tid;
  [352] int *clear_child_tid;
  [356] cputime_t utime;
  [360] cputime_t stime;
  [364] cputime_t utimescaled;
  [368] cputime_t stimescaled;
  [372] cputime_t gtime;
  [376] cputime_t prev_utime;
  [380] cputime_t prev_stime;
  [384] unsigned long nvcsw;
  [388] unsigned long nivcsw;
  [392] struct timespec start_time;
  [400] struct timespec real_start_time;
  [408] unsigned long min_flt;
  [412] unsigned long maj_flt;
  [416] struct task_cputime cputime_expires;
  [432] struct list_head cpu_timers[3];
  [456] const struct cred *real_cred;
  [460] const struct cred *cred;
  [464] struct cred *replacement_session_keyring;
  [468] char comm[16];
  [484] int link_count;
  [488] int total_link_count;
  [492] struct sysv_sem sysvsem;
  [496] unsigned long last_switch_count;
  [500] struct thread_struct thread;
  [512] struct fs_struct *fs;
  [516] struct files_struct *files;
  [520] struct nsproxy *nsproxy;
  [524] struct signal_struct *signal;
  [528] struct sighand_struct *sighand;
  [532] sigset_t blocked;
  [540] sigset_t real_blocked;
  [548] sigset_t saved_sigmask;
  [556] struct sigpending pending;
  [572] unsigned long sas_ss_sp;
  [576] size_t sas_ss_size;
  [580] int (*notifier)(void *);
  [584] void *notifier_data;
  [588] sigset_t *notifier_mask;
  [592] struct audit_context *audit_context;
  [596] seccomp_t seccomp;
  [596] u32 parent_exec_id;
  [600] u32 self_exec_id;
  [604] spinlock_t alloc_lock;
  [608] raw_spinlock_t pi_lock;
  [612] struct plist_head pi_waiters;
  [620] struct rt_mutex_waiter *pi_blocked_on;
  [624] void *journal_info;
  [628] struct bio_list *bio_list;
  [632] struct blk_plug *plug;
  [636] struct reclaim_state *reclaim_state;
  [640] struct backing_dev_info *backing_dev_info;
  [644] struct io_context *io_context;
  [648] unsigned long ptrace_message;
  [652] siginfo_t *last_siginfo;
  [656] struct task_io_accounting ioac;
  [656] struct robust_list_head *robust_list;
  [660] struct list_head pi_state_list;
  [668] struct futex_pi_state *pi_state_cache;
  [672] struct rcu_head rcu;
  [680] struct pipe_inode_info *splice_pipe;
  [684] int nr_dirtied;
  [688] int nr_dirtied_pause;
  [692] unsigned long dirty_paused_when;
  [696] unsigned long timer_slack_ns;
  [700] unsigned long default_timer_slack_ns;
  [704] struct list_head *scm_work_list;
}
SIZE: 712

crash> mm_struct -o

struct mm_struct {
    [0] struct vm_area_struct *mmap;
    [4] struct rb_root mm_rb;
    [8] struct vm_area_struct *mmap_cache;
   [12] unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);
   [16] void (*unmap_area)(struct mm_struct *, unsigned long);
   [20] unsigned long mmap_base;
   [24] unsigned long task_size;
   [28] unsigned long cached_hole_size;
   [32] unsigned long free_area_cache;
   [36] pgd_t *pgd;
   [40] atomic_t mm_users;
   [44] atomic_t mm_count;
   [48] int map_count;
   [52] spinlock_t page_table_lock;
   [56] struct rw_semaphore mmap_sem;
   [72] struct list_head mmlist;
   [80] unsigned long hiwater_rss;
   [84] unsigned long hiwater_vm;
   [88] unsigned long total_vm;
   [92] unsigned long locked_vm;
   [96] unsigned long pinned_vm;
  [100] unsigned long shared_vm;
  [104] unsigned long exec_vm;
  [108] unsigned long stack_vm;
  [112] unsigned long reserved_vm;
  [116] unsigned long def_flags;
  [120] unsigned long nr_ptes;
  [124] unsigned long start_code;
  [128] unsigned long end_code;
  [132] unsigned long start_data;
  [136] unsigned long end_data;
  [140] unsigned long start_brk;
  [144] unsigned long brk;
  [148] unsigned long start_stack;
  [152] unsigned long arg_start;
  [156] unsigned long arg_end;
  [160] unsigned long env_start;
  [164] unsigned long env_end;
  [168] unsigned long saved_auxv[40];
  [328] struct mm_rss_stat rss_stat;
  [340] struct linux_binfmt *binfmt;
  [344] cpumask_var_t cpu_vm_mask_var;
  [348] mm_context_t context;
  [360] unsigned int faultstamp;
  [364] unsigned int token_priority;
  [368] unsigned int last_interval;
  [372] unsigned long flags;
  [376] struct core_state *core_state;
  [380] spinlock_t ioctx_lock;
  [384] struct hlist_head ioctx_list;
  [388] struct file *exe_file;
  [392] unsigned long num_exe_file_vmas;
}

下面的问题是怎样设怎样维护每CPU runqueues的?

1. 怎样把唤醒的task 加入run queue?

2. 怎样把睡眠的task中从runqueue中删除



这篇关于scheduler 怎样得到 next task_struct的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1027480

相关文章

你的华为手机升级了吗? 鸿蒙NEXT多连推5.0.123版本变化颇多

《你的华为手机升级了吗?鸿蒙NEXT多连推5.0.123版本变化颇多》现在的手机系统更新可不仅仅是修修补补那么简单了,华为手机的鸿蒙系统最近可是动作频频,给用户们带来了不少惊喜... 为了让用户的使用体验变得很好,华为手机不仅发布了一系列给力的新机,还在操作系统方面进行了疯狂的发力。尤其是近期,不仅鸿蒙O

C# Task Cancellation使用总结

《C#TaskCancellation使用总结》本文主要介绍了在使用CancellationTokenSource取消任务时的行为,以及如何使用Task的ContinueWith方法来处理任务的延... 目录C# Task Cancellation总结1、调用cancellationTokenSource.

C和指针:结构体(struct)和联合(union)

结构体和联合 结构体 结构体包含一些数据成员,每个成员可能具有不同的类型。 数组的元素长度相同,可以通过下标访问(转换为指针)。但是结构体的成员可能长度不同,所以不能用下标来访问它们。成员有自己的名字,可以通过名字访问成员。 结构声明 在声明结构时,必须列出它包含的所有成员。 struct tag {member-list} variable-list ; 定义一个结构体变量x(包含

LabVIEW程序员是怎样成长为大佬

成为一名LabVIEW编程领域的“大佬”需要时间、实践、学习和解决复杂问题的经验。尽管LabVIEW作为一种图形化编程语言在初期可能相对容易上手,但要真正成为精通者,需要在多个层面上深入理解。以下是LabVIEW程序员如何逐步成长为“大佬”的路径: 1. 打好基础 LabVIEW的大佬们通常在初期会打下非常坚实的基础,理解LabVIEW编程的核心概念,包括: 数据流编程模型:Lab

【鸿蒙HarmonyOS NEXT】页面之间相互传递参数

【鸿蒙HarmonyOS NEXT】页面之间相互传递参数 一、环境说明二、页面之间相互传参 一、环境说明 DevEco Studio 版本: API版本:以12为主 二、页面之间相互传参 说明: 页面间的导航可以通过页面路由router模块来实现。页面路由模块根据页面url找到目标页面,从而实现跳转。通过页面路由模块,可以使用不同的url访问不同的页面,包括跳转到U

十四、我们应当怎样做需求分析:子用例与扩展用例

用例模型作为UML中4+1视图中非常重要的一员,非常集中地体现了面向对象的分析与设计思想。用例模型将现实世界中连续的一个一个业务流程,按照场景划分到了一个一个的用例中。由于场景的出现,使得用例中的业务流程存在着高度的内聚性,从而成为了日后各种对象的雏形。同时,在用例分析中,又将那些存在于各个用例中的,相同或相近的业务操作提取出来,形成一个一个的子用例或扩展用例,又体现了面向对象设计中的复用性。现在

十三、我们应当怎样做需求分析:查询报表分析

在我以往的用例分析中,使用这样格式的用例模式,对于大多数业务操作流程来说是得心应手的,但对于有些功能来说总感觉不对劲。感觉不对劲的,就是那些查询、汇总与报表功能。对于这部分功能,需要我们描述的不是什么操作流程,而更重要的是那些数据项、数据来源、报表格式、数据链接,以及使用者、使用频率的说明。而这些,在以往的用例说明格式中统统都没有,怎么办呢?俗话说“东西是死的人是活的”,把我们的用例格式改改吧。

九、我们应当怎样做需求分析:功能角色分析与用例图

在我们进行一系列需求调研工作的同时,我们的需求分析工作也开始启动了。需求调研与需求分析工作应当是相辅相伴共同进行的。每次参加完需求调研回到公司,我们就应当对需求调研的成果进行一次需求分析。当下一次开始进行需求调研时,我们应当首先将上次需求分析的结果与客户进行确认,同时对需求分析中提出的疑问交给客户予以解答。这就是一个需求捕获->需求整理->需求验证->再需求捕获的过程。  但是,当我们经

八、我们应当怎样做需求调研:需求捕获(下)

前面我们讨论了,需求分析工作是一个迭代的过程:需求捕获->需求整理->需求验证->再需求捕获······需求捕获是这个迭代过程的开始,也是整个需求分析工作中最重要的部分。没有捕获哪来后面的整理与验证工作?但是,非常遗憾,按照我以往的经验,需求捕获是我们最薄弱的环节。前面我提到的许许多多项目开发的问题都可以归结为需求分析的问题,而许许多多需求分析的问题又都可以归结为需求捕获不完整的问题。需求捕获是整

七、我们应当怎样做需求调研:需求捕获(上)

前面我们讨论了,需求分析工作是一个迭代的过程:需求捕获->需求整理->需求验证->再需求捕获······需求捕获是这个迭代过程的开始,也是整个需求分析工作中最重要的部分。没有捕获哪来后面的整理与验证工作?但是,非常遗憾,按照我以往的经验,需求捕获是我们最薄弱的环节。前面我提到的许许多多项目开发的问题都可以归结为需求分析的问题,而许许多多需求分析的问题又都可以归结为需求捕获不完整的问题。需求捕获是整