sched_post_fork 详细解读
时间: 2023-08-05 13:09:14 浏览: 69
`sched_post_fork` 是 Linux 内核中的一个函数,用于在进程 fork 后更新子进程的调度信息。在进程 fork 后,子进程需要继承父进程的调度信息,包括进程的优先级、调度策略、调度参数等。`sched_post_fork` 函数主要负责为子进程更新这些调度信息,以确保子进程能够正确地被调度执行。
具体来说,`sched_post_fork` 函数会在进程 fork 后被调用,用于更新子进程的调度信息。该函数会首先从父进程中复制进程的调度信息,并为子进程设置相应的标志位。然后,该函数会为子进程创建新的调度实体,并将其加入到任务队列中,以等待被调度执行。
在为子进程创建调度实体时,`sched_post_fork` 函数会根据子进程的调度策略和调度参数等信息,创建相应的调度实体。在 Linux 内核中,不同的调度策略和调度参数会对应不同的调度实体,如进程控制块(PCB)、调度类和调度器等。因此,在为子进程创建调度实体时,需要根据子进程的调度策略和调度参数等信息来进行相应的选择和创建。
需要注意的是,`sched_post_fork` 函数主要用于为子进程更新调度信息和创建调度实体,并将其加入到任务队列中。具体的调度过程和调度策略等信息,是由 CFS 调度器来进行实现和维护的。因此,在理解 `sched_post_fork` 函数的实现时,需要结合 CFS 调度器的内部实现和调度策略等信息进行理解。
相关问题
sched_post_fork
sched_post_fork 是 Linux 内核中的一个函数,用于在进程 fork 完成后,为子进程重新设置调度策略和优先级等信息。
具体来说,当一个进程调用 fork 函数时,内核会创建一个新的进程作为它的子进程。在创建子进程后,内核会调用 sched_post_fork 函数来为子进程重新设置调度策略和优先级等信息,以便子进程可以继承父进程的调度属性,并在之后的调度中得到正确的调度。
sched_post_fork 函数会首先获取当前进程的调度锁,以避免并发修改对调度属性的影响。然后,它会将子进程的调度策略和优先级设置为与父进程相同的值。接着,它会根据情况调整子进程的调度器状态,并将其加入到对应的运行队列中,等待被调度执行。
需要注意的是,子进程继承了父进程的大部分属性,但也有一些属性是需要重新设置的。例如,子进程需要重新设置进程 ID、文件描述符等信息。此外,子进程还需要重新设置资源限制、信号处理器等信息,以确保它的运行环境与父进程相同。
sched_post_fork 源码
下面是 `sched_post_fork` 函数的部分源码,代码摘自 Linux 内核版本 5.15.5:
```c
void sched_post_fork(struct task_struct *p)
{
struct rq_flags rf;
struct sched_entity *se = &p->se;
struct task_struct *parent = p->parent;
struct sched_entity *parent_se = &parent->se;
if (parent_se->on_rq && !se->on_rq) {
/*
* parent is on a runqueue, but we just forked the child and it's
* not on any runqueue yet. This means we need to do a few things
* to get the child properly accounted for.
*/
p->se.load.weight = 0;
se->vruntime = parent_se->vruntime;
se->sum_exec_runtime = parent_se->sum_exec_runtime;
se->prev_sum_exec_runtime = parent_se->prev_sum_exec_runtime;
se->avg_overlap = parent_se->avg_overlap;
/*
* We need to add the child to the runqueue. This is tricky, as
* we cannot just add it to the parent's runqueue, as that would
* mess up the order of the tasks. Instead, we need to add it
* to the right runqueue based on its priority.
*/
raw_spin_lock_irqsave(&rq_lock(p), rf);
enqueue_task_rq(p, task_cpu(p), ENQUEUE_WAKEUP);
raw_spin_unlock_irqrestore(&rq_lock(p), rf);
}
/*
* We need to reset the child's CPU time and other accounting
* information, as it is starting fresh.
*/
schedstat_set(p->se.statistics.wait_start, 0);
cpuacct_clear_stats(p);
memset(&p->sched_info, 0, sizeof(p->sched_info));
}
```
该函数主要做了以下几件事情:
1. 复制父进程的调度实体信息,包括进程的优先级、调度策略、调度参数等;
2. 为子进程创建新的调度实体,并将其加入到任务队列中;
3. 重置子进程的 CPU 时间和其他计算信息,以确保子进程可以从头开始执行。
需要注意的是,`sched_post_fork` 函数只是为子进程更新调度信息和创建调度实体,并将其加入到任务队列中。具体的调度过程和调度策略等信息,是由 CFS 调度器来进行实现和维护的。因此,在理解 `sched_post_fork` 函数的实现时,需要结合 CFS 调度器的内部实现和调度策略等信息进行理解。