调度器的初始化,前面的android 开机流程讲过,uboot(bootloader)执行完一些初始化动作后,会将kernel加载到内存,然后跳到kernel。
kernel在执行完一段汇编代码,准备好c的运行环境后,跳到 start_kernel()。
sched_init() 初始化了很多调度相关的数据结构,下面只会把它们简单列出来
kernel在执行完一段汇编代码,准备好c的运行环境后,跳到 start_kernel()。
linux-4.10/init/main.c
linux-4.10/init/main.c
482 asmlinkage __visible void __init start_kernel(void)
483 {
...
542 /*
543 * Set up the scheduler prior starting any interrupts (such as the
544 * timer interrupt). Full topology setup happens at smp_init()
545 * time - but meanwhile we still have a functioning scheduler.
546 */
547 sched_init(); //调度器的初始化
...
672 /* Do the rest non-__init'ed, we're now alive */
673 rest_init();
674 }
sched_init() 初始化了很多调度相关的数据结构,下面只会把它们简单列出来
linux-4.10/kernel/sched/core.c
linux-4.10/kernel/sched/core.c
7543 void __init sched_init(void)
7544 {
7545 int i, j;
7546 unsigned long alloc_size = 0, ptr;
7547
/*
* linux-4.10/include/linux/types.h
* struct list_head { //双向链表
* struct list_head *next, *prev;
* };
* linux-4.10/include/linux/wait.h
* struct __wait_queue_head { //所以__wait_queue_head 是一个双向链表,用于保存 spinlock_t (自旋锁)
* spinlock_t lock;
* struct list_head task_list;
* };
typedef struct __wait_queue_head wait_queue_head_t;
*/
7548 for (i = 0; i < WAIT_TABLE_SIZE; i++) // #define WAIT_TABLE_BITS 8 #define WAIT_TABLE_SIZE (1 << WAIT_TABLE_BITS) 所以WAIT_TABLE_SIZE 等于 256
7549 init_waitqueue_head(bit_wait_table + i); //static wait_queue_head_t bit_wait_table[WAIT_TABLE_SIZE] __cacheline_aligned;
7550
7551 #ifdef CONFIG_FAIR_GROUP_SCHED //普通进程调度
7552 alloc_size += 2 * nr_cpu_ids * sizeof(void **); //nr_cpu_ids 为支持的cpu核个数,也就是常说的几核,64位系统上 sizeof(void **) = 8
7553 #endif
7554 #ifdef CONFIG_RT_GROUP_SCHED //实时进程调度
7555 alloc_size += 2 * nr_cpu_ids * sizeof(void **);
7556 #endif
7557 if (alloc_size) {
7558 ptr = (unsigned long)kzalloc(alloc_size, GFP_NOWAIT); //申请内存
7559
7560 #ifdef CONFIG_FAIR_GROUP_SCHED
7561 root_task_group.se = (struct sched_entity **)ptr; //指向调度实体
7562 ptr += nr_cpu_ids * sizeof(void **);//ptr指针移动nr_cpu_ids * sizeof(void **) nr_cpu_ids, 为支持的cpu核个数,64位系统上 sizeof(void **) = 8
7563
7564 root_task_group.cfs_rq = (struct cfs_rq **)ptr; //指向调度队列指针,每个核有一个调度队列
7565 ptr += nr_cpu_ids * sizeof(void **);//ptr指针移动nr_cpu_ids * sizeof(void **) nr_cpu_ids,为支持的cpu核个数,64位系统上 sizeof(void **) = 8
7566
7567 #endif /* CONFIG_FAIR_GROUP_SCHED */
7568 #ifdef CONFIG_RT_GROUP_SCHED
7569 root_task_group.rt_se = (struct sched_rt_entity **)ptr; //
7570 ptr += nr_cpu_ids * sizeof(void **); //ptr指针移动nr_cpu_ids * sizeof(void **) nr_cpu_ids, 为支持的cpu核个数,64位系统上 sizeof(void **) = 8
7571
7572 root_task_group.rt_rq = (struct rt_rq **)ptr; //
7573 ptr += nr_cpu_ids * sizeof(void **);
7574
7575 #endif /* CONFIG_RT_GROUP_SCHED */
7576 }
7577 #ifdef CONFIG_CPUMASK_OFFSTACK
7578 for_each_possible_cpu(i) { // (1)...
7579 per_cpu(load_balance_mask, i) = (cpumask_var_t)kzalloc_node(
7580 cpumask_size(), GFP_KERNEL, cpu_to_node(i));
7581 per_cpu(select_idle_mask, i) = (cpumask_var_t)kzalloc_node(
7582 cpumask_size(), GFP_KERNEL, cpu_to_node(i));
7583 }
7584 #endif /* CONFIG_CPUMASK_OFFSTACK */
7585 // (2)...
7586 init_rt_bandwidth(&def_rt_bandwidth, //初始化实时进程对cpu的占有率 ,超过会有一定的惩罚机制(rt throttled)
7587 global_rt_period(), global_rt_runtime());
7588 init_dl_bandwidth(&def_dl_bandwidth,
7589 global_rt_period(), global_rt_runtime());
7590
7591 #ifdef CONFIG_SMP
7592 init_defrootdomain(); // (3)...
7593 #endif
7594
7595 #ifdef CONFIG_RT_GROUP_SCHED
7596 init_rt_bandwidth(&root_task_group.rt_bandwidth,/初始化root_task_group进程组实时进程对cpu的占有率
7597 global_rt_period(), global_rt_runtime());
7598 #endif /* CONFIG_RT_GROUP_SCHED */
7599
7600 #ifdef CONFIG_CGROUP_SCHED //如果支持进程组,可以理解为多用户,每个用户下面的所有进程为一个进程组
7601 task_group_cache = KMEM_CACHE(task_group, 0);
7602
7603 list_add(&root_task_group.list, &task_groups); //将root_task_group添加到task_groups队列中
7604 INIT_LIST_HEAD(&root_task_group.children);
7605 INIT_LIST_HEAD(&root_task_group.siblings);
7606 autogroup_init(&init_task);
7607 #endif /* CONFIG_CGROUP_SCHED */
7608
7609 for_each_possible_cpu(i) {
7610 struct rq *rq;
/*
* linux-4.10/kernel/sched/sched.h
* struct rq {
* /* runqueue lock: */
* raw_spinlock_t lock; //自旋锁
* ...
* 604 unsigned int nr_running; //此CPU上总共就绪的进程数
* ...
* u64 nr_switches; // 进行上下文切换次数
*
* struct cfs_rq cfs; // cfs调度运行队列
* struct rt_rq rt; //实时调度运行队列
* struct dl_rq dl; //dl调度运行队列
* ...
* struct task_struct *curr, *idle, *stop;