5

我了解到,设置一个非零值/proc/sys/kernel/sched_child_runs_first将强制子进程在父进程之前运行。但是,我认为它似乎不起作用。这是我的代码:

#include <stdio.h>
#include <sys/types.h>

int main(int argc, char **argv)
{
  pid_t child_pid;

  switch(child_pid = fork())
    {
    case 0:
      printf("In Child\n");
      exit(0);

    case -1:
      printf("Could not fork()\n");

    default:
      printf("In parent\n");

    }
  return 0;
}

我得到的输出总是:

In parent
In Child

我期待这里有什么问题吗?

PS:我只是在尝试看看它是否有效,所以请不要建议其他同步机制或为什么这是一个坏主意等。

4

1 回答 1

8

据我所知,sched_child_runs_first实现该功能的地方在task_fork_fair函数中,您可以在此处查看其源代码。

该函数的关键部分如下所示:

if (curr)
        se->vruntime = curr->vruntime;
place_entity(cfs_rq, se, 1);

if (sysctl_sched_child_runs_first && curr && entity_before(curr, se)) {
        swap(curr->vruntime, se->vruntime);
        resched_task(rq->curr);
}

se是新的调度实体,curr是当前任务的调度实体。

请注意,新实体的vruntime首先使用与当前任务相同的值进行初始化。这很重要,因为该entity_before调用正在检查currvruntime是否小于sevruntime

因此,该条件成功的唯一方法是place_entity调用将se的vruntime设置为更大的值。所以让我们看看它的来源。关键位是:

u64 vruntime = cfs_rq->min_vruntime;

if (initial && sched_feat(START_DEBIT))
        vruntime += sched_vslice(cfs_rq, se);

se->vruntime = max_vruntime(se->vruntime, vruntime);

因此,假设该START_DEBIT功能已设置(似乎是这种情况),那么vruntime将设置为运行队列的min_vruntime加上sched_vslice调用返回的任何内容。如果这大于当前的vruntime,那么我们就设置好了 - 如果不是,我们将留下我们的初始vruntime值并且条件不会成功。

我对 Linux 调度的理解还不够好,不能肯定地说,但我猜min_vruntime plussched_vslice在大多数情况下都不够大。

我说大部分时间是因为,当我进行测试时,至少在某些时候我能够让子进程首先运行。因此,该sched_child_runs_first参数可能确实会有所不同-它不能保证任何事情。

另一种可能是代码中的错误,在计算函数中的初始值时,它们应该从当前任务的vruntime而不是运行队列的min_vruntimeplace_entity开始。那将保证条件会成功。但我怀疑以我不明白的方式做事是有原因的。

于 2013-06-30T18:01:56.230 回答