【问题标题】:Writing a syscall to count context switches of a process编写系统调用来计算进程的上下文切换
【发布时间】:2023-03-03 18:37:02
【问题描述】:

我必须进行系统调用来计算进程的自愿和非自愿上下文切换。我已经知道向 linux 内核添加新系统调用的步骤,但我不知道应该从哪里开始上下文切换功能。有什么想法吗?

【问题讨论】:

标签: linux operating-system linux-kernel context-switch


【解决方案1】:

如果您的系统调用应该只报告统计信息,您可以使用内核中已经存在的上下文切换计数代码。

wait3 syscallgetrusage syscall 已在 struct rusage 字段中报告上下文切换计数:

struct rusage {
 ...
    long   ru_nvcsw;         /* voluntary context switches */
    long   ru_nivcsw;        /* involuntary context switches */
};

你可以通过运行来试试:

$ /usr/bin/time -v /bin/ls -R
....
    Voluntary context switches: 1669
    Involuntary context switches: 207

其中“/bin/ls -R”是任何程序。

通过在内核源代码中搜索“struct rusage”,您可以在 kernel/sys.c 中找到this accumulate_thread_rusage,它会更新 rusage 结构。它来自struct task_struct *tt->nvcsw;t->nivcsw; 字段:

1477  static void accumulate_thread_rusage(struct task_struct *t, struct rusage *r)
1478  {
1479        r->ru_nvcsw += t->nvcsw;    // <<=== here
1480        r->ru_nivcsw += t->nivcsw;
1481        r->ru_minflt += t->min_flt;
1482        r->ru_majflt += t->maj_flt;

然后您应该在内核文件夹中搜索nvcswnivcsw 以查找它们是如何被内核更新的。

asmlinkage void __sched schedule(void):

4124     if (likely(prev != next)) {         // <= if we are switching between different tasks
4125            sched_info_switch(prev, next);
4126            perf_event_task_sched_out(prev, next);
4127
4128            rq->nr_switches++;          
4129            rq->curr = next;
4130            ++*switch_count;     // <= increment nvcsw or nivcsw via pointer
4131
4132            context_switch(rq, prev, next); /* unlocks the rq */

指针switch_count 来自同一文件的line 4091line 4111

PS:来自 perreal 的链接很棒:http://oreilly.com/catalog/linuxkernel/chapter/ch10.html(搜索context_swtch

【讨论】:

    【解决方案2】:

    这已经存在:虚拟文件/proc/NNNN/status(其中 NNNN 是您想要了解的进程的十进制进程 ID)包含自愿和非自愿上下文切换的计数等。与getrusage 不同,这允许您了解任何 进程的上下文切换计数,而不仅仅是子进程。有关详细信息,请参阅proc(5) manpage

    【讨论】:

      【解决方案3】:

      进程将在阻塞、时间量子到期或中断等情况下进行上下文切换。最终调用 schedule() 函数。由于您想分别为每个进程计算它,因此您必须为每个进程保留一个新变量以计算上下文切换的数量。并且您可以在当前进程的调度乐趣中每次更新此变量。使用您的系统调用,您可以读取此值。这是pintos的schedule函数的sn-p,

      static void
      schedule (void) 
      {
        struct thread *cur = running_thread ();
        struct thread *next = next_thread_to_run ();
        struct thread *prev = NULL;
      
        ASSERT (intr_get_level () == INTR_OFF);
        ASSERT (cur->status != THREAD_RUNNING);
        ASSERT (is_thread (next));<br/>
      
        if (cur != next)
          prev = switch_threads (cur, next);  <== here you can update count of "cur"   
        thread_schedule_tail (prev);
      }  
      

      【讨论】:

        【解决方案4】:

        上下文切换的总数

        cat /proc/PID/sched|grep nr_switches

        自愿上下文切换

        cat /proc/PID/sched | grep nr_voluntary_switches

        非自愿上下文切换

        cat /proc/PID/sched|grep nr_involuntary_switches

        其中 PID 是您希望监控的进程的进程 ID。

        但是,如果您想通过修补(创建挂钩)linux 源来获取这些统计信息,则与调度相关的代码存在于

        内核/调度/

        源树的文件夹。 特别是

        kernel/sched/core.c 包含 schedule() 函数,是 linux 调度器的代码。 CFS(完全公平调度器)的代码,它是 Linux 中存在的几个调度器之一,并且最常用的是存在于

        /kernel/sched/fair.c

        scheduler() 在设置 TIF_NEED_RESCHED 标志时执行,因此找出设置此标志的所有位置(在 linux 源代码上使用 cscope),这将使您深入了解发生的上下文切换类型过程。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2012-02-11
          • 2020-11-01
          • 2016-11-06
          • 2012-09-18
          • 2020-04-03
          • 2021-11-18
          • 2015-03-16
          相关资源
          最近更新 更多