Linux 编写系统调用以计数进程的上下文开关

Linux 编写系统调用以计数进程的上下文开关,linux,operating-system,linux-kernel,context-switch,Linux,Operating System,Linux Kernel,Context Switch,我必须执行一个系统调用来计算进程的自愿和非自愿上下文切换。我已经知道向linux内核添加新系统调用的步骤,但是我不知道应该从哪里开始上下文切换函数。有什么想法吗?进程将在阻塞、时间量过期或中断等情况下进行上下文切换。最终调用schedule()函数。由于要分别为每个进程计算它,因此必须为每个进程保留一个新变量,用于计算上下文开关的数量。您可以在当前流程的schedule fun中每次更新此变量。使用系统调用可以读取此值。下面是pintos的schedule函数的一个片段 static void

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

进程将在阻塞、时间量过期或中断等情况下进行上下文切换。最终调用schedule()函数。由于要分别为每个进程计算它,因此必须为每个进程保留一个新变量,用于计算上下文开关的数量。您可以在当前流程的schedule fun中每次更新此变量。使用系统调用可以读取此值。下面是pintos的schedule函数的一个片段

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);
}  
静态无效
附表(无效)
{
struct thread*cur=running_thread();
struct thread*next=next_thread_to_run();
结构线程*prev=NULL;
断言(intr\u get\u level()==intr\u OFF);
断言(cur->status!=线程运行);
断言(是线程(下一个));
如果(cur!=下一个)
prev=switch_threads(cur,next);如果系统调用只报告统计信息,那么可以使用内核中已有的上下文切换计数代码

或已在
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中找到,它更新了rusage struct。它从
struct task\u struct*t
;字段
t->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;
指针
switch\u count
来自或属于同一文件


PS:来自perreal的链接很好:(搜索
context\u swtch

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

上下文切换总数

cat/proc/PID/sched|grep nr_开关

自愿上下文切换

cat/proc/PID/sched|grep nr_自愿_开关

非自愿上下文切换

cat/proc/PID/sched|grep nr_非自愿_开关

其中PID是要监视的进程的进程ID

但是,如果您希望通过修补(创建一个钩子)linux源代码来获得这些统计信息,那么与调度相关的代码将显示在中

内核/调度/

源目录树的文件夹。 特别是

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

/kernel/sched/fair.c

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

查看sched()函数。
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 */