1、idle thread是什么
idle thread是每个CPU的0号线程,在CPU启动过程中生成,当该CPU上没有用户任务线程和内核任务线程(如kworker、ksoftirqd等)时,CPU运行0号线程、以表明该CPU进入空闲状态。
2、idle thread的初始化过程
文章以下内容所涉及到的系统架构是arm64,源码版本为linux kernel 5.10.158在介绍idle thread初始化过程前先介绍两个结构体struct task_struct和struct rq。
2.1 struct task_struct
struct task_struct用于描述该进程的运行信息,常见的成员优先级priority、调度策略(实时策略or公平调度策略)、当前状态state(已停止、可以运行or不可运行)等,具体的函数定义可查询./include/linux/sched.h(.表示源码根目录)。idle thread可被看作只有一个线程的进程,其线程情况,可以用struct task_struct表达。
2.2 struct rq
struct rq用于描述该CPU上的运行队列情况。每一个处于运行状态的CPU都有且只有一个struct rq结构体。该结构体常见的成员有运行队列锁lock、当前运行进程*curr、CPU空闲时运行线程*idle等。在每个CPU上,idle thread被分配给每个CPU的struct rq的成员idle,当CPU进入空闲状态时,CPU切换到idle thread线程运行。该结构体的具体定义同样也可查询./include/linux/sched.h
2.3 idle thread的初始化路径
在下图中,箭头代表函数中的调用。下图为idle thread大致的初始化过程。
init_idle的参数current数据类型是struct task_struct*,在这里具体内容是执行当前线程的struct task_struct结构体的指针,由于执行初始化过程的即为0号线程idle thread,实际上这里的current即为表达idle thread的task_struct结构体的指针。smp_processor_id()为当前执行该任务流的CPU序号。
下边为init_idle()部分源代码,这些代码是idle thread初始化过程中较为重要的地方。
void __init init_idle(struct task_struct *idle, int cpu)
{
struct rq *rq = cpu_rq(cpu);//获取当前CPU上的运行队列rq
//.......
idle->state = TASK_RUNNING;//将idle thread的状态设置为运行中
idle->se.exec_start = sched_clock();
idle->flags |= PF_IDLE;
//......
rq->idle = idle;//运行队列rq的idle线程设置
rcu_assign_pointer(rq->curr, idle);
idle->on_rq = TASK_ON_RQ_QUEUED;//将idle任务添加到rq运行队列中,可被调度
//......
}
3、操作系统从开启到CPU进入idle状态的全过程
下图为操作系统所有CPU从启动到进入idle状态的全过程流程图。
在上图中,start_kernel()至rest_init()是boot cpu负责运行的,secondary_start_kernel()是非boot cpu负责运行的。 start_kernel()和secondary_start_kernel()两者之前的部分(黑线向上),表示启动bios主板的过程,在这里不做叙述。函数cpu_startup_entry()的具体定义如下:
void cpu_startup_entry(enum cpuhp_state state)
{
arch_cpu_idle_prepare();
cpuhp_online_idle(state);
while (1)
do_idle();//进入循环
}
从cpu_startup_entry()开始,操作系统内核启动完毕,当该CPU处于空闲状态时,idle thread反复运行do_idle()函数 。若运行do_idle()函数过程中,没有其他任务线程切入,则idle thread运行cpuidle_idle_call(),准备运行idle state状态的内容。在架构arm64中,idle state状态只有一个,即CPU运行汇编指令wfi()。
wfi()指令是一个阻塞类型的指令,wfi全程为wait for interrupt(等待中断),当没有中断发生时,CPU运行阻塞在wfi()指令,不会运行其他指令。arm64架构用这种方式实现了CPU在空闲时的低功耗状态。
4、下一篇文章
下一篇文章我会介绍在arm64架构下的wfi()、hlt()以及nop()指令,以及idle state的选择及编译选项CONFIG_CPU_IDLE