目录
在Linux内核中,任务入队(即将任务放入CPU的就绪队列)是调度器的核心操作之一。任务入队通常发生在以下几种情况下:
-
任务被唤醒:当一个任务从睡眠状态(如等待I/O、信号量等)被唤醒时,它会被放入就绪队列。
-
新任务创建:当一个新任务(如通过
fork()
或pthread_create()
创建)被创建时,它会被放入就绪队列。 -
任务迁移:在多核系统中,任务可能会从一个CPU迁移到另一个CPU,这时任务会被放入目标CPU的就绪队列。
-
负载均衡:在多核系统中,调度器会进行负载均衡,将任务从一个CPU迁移到另一个CPU,这时任务会被放入目标CPU的就绪队列。
1. 任务入队的触发条件
1.1 任务被唤醒
当一个任务从睡眠状态被唤醒时,内核会调用try_to_wake_up
函数,该函数最终会调用enqueue_task
将任务放入就绪队列。
/*
* try_to_wake_up - 尝试唤醒一个任务
* @p: 要唤醒的任务
* @state: 任务的状态
* @wake_flags: 唤醒标志
*/
static int try_to_wake_up(struct task_struct *p, unsigned int state, int wake_flags)
{
int cpu, success = 0;
cpu = select_task_rq(p, p->wake_cpu, wake_flags | WF_TTWU); // 选择目标CPU
if (cpu != task_cpu(p)) { // 如果目标CPU与当前CPU不同
set_task_cpu(p, cpu); // 设置任务的目标CPU
}
ttwu_queue(p, cpu, wake_flags); // 将任务放入目标CPU的就绪队列
return success;
}
try_to_wake_up
函数的主要步骤如下:
-
选择目标CPU:
select_task_rq
函数用于选择目标CPU。这个函数会根据任务的亲和性(affinity)和负载均衡策略选择一个合适的CPU。 -
设置任务的目标CPU:如果目标CPU与当前CPU不同,则调用
set_task_cpu
函数设置任务的目标CPU。 -
将任务放入目标CPU的就绪队列:
ttwu_queue
函数用于将任务放入目标CPU的就绪队列。
1.2 新任务创建
当一个新任务被创建时,内核会调用wake_up_new_task
函数,该函数最终会调用enqueue_task
将任务放入就绪队列。
/*
* wake_up_new_task - 唤醒一个新任务
* @p: 新任务
*/
void wake_up_new_task(struct task_struct *p)
{
struct rq *rq;
int cpu;
cpu = select