/proc/sys/kernel/sched_child_runs_first是否有效?

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

我在这里期待了什么吗?

附注:我只是在进行实验,想看看它是否有效,请勿提出其他同步机制或者为什么这是一个不好的想法等建议。


1
你有看过这个吗:http://yarchive.net/comp/linux/child-runs-first.html? - Aman Deep Gautam
@AmanDeepGautam 感谢提供的链接。是的,我也读了 Michael Kerrisk 的书中的大部分内容。但他建议在上述文件中设置该值“保证”子进程将首先运行,或者我可能读错了。 - user59634
但是链接显示他们正在从内核版本2.6中删除对此的支持,我找不到更新的帖子,说明他们已经再次添加了支持。所以也许这种方式不可能,但我不是这方面的权威.. :) - Aman Deep Gautam
@AmanDeepGautam 或许我需要深入挖掘,除非有人能够确认。无论如何,谢谢。 - user59634
使用以下指令在搭载Raspbian的Raspberry Pi Zero上: $ sudo echo "1" > /proc/sys/kernel/sched_child_runs_first $ ./fork_whos_on_first 10000 > fork.txt $ ./fork_whos_on_first.count.awk fork.txt 我得到了以下数字(与“0”的100%,100%相比): 子进程21个,占0.21%, 父进程9979个,占99.79%。 - tamberg
这是来自Linus Torvalds的一封电子邮件,链接为https://yarchive.net/comp/linux/child-runs-first.html,其中解释了一些权衡,并声明没有任何保证。 - tamberg
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呼叫将sevruntime设为更大的值时,该条件才会成功。所以让我们看一下source。关键部分如下:
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加上sched_vslice在大多数情况下都不够大。
我说“大多数情况”,因为在测试时,我至少有一些时间能让子进程首先运行。因此,sched_child_runs_first参数可能会起作用-只是不能保证任何事情。
另一个可能性是代码中存在错误,他们在计算“place_entity”函数中的初始值时应该使用当前任务的“vruntime”,而不是运行队列的“min_vruntime”。这将确保条件会成功。但我怀疑他们采用这种方式做事情肯定有原因,只是我不理解而已。

谢谢您的回答。我会花些时间仔细阅读。 - user59634

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接