Написание системного вызова для подсчета переключений контекста процесса

Мне нужно сделать системный вызов, чтобы подсчитать добровольные и непроизвольные переключения контекста процесса. Я уже знаю шаги по добавлению нового системного вызова в ядро ​​Linux, но понятия не имею, с чего начать для функции переключения контекста. Есть идеи?


person Nausikaa    schedule 14.02.2012    source источник
comment
Посмотрите на функцию sched(). oreilly.com/catalog/linuxkernel/chapter/ch10.html   -  person perreal    schedule 15.02.2012


Ответы (4)


Если ваш системный вызов должен сообщать только статистику, вы можете использовать код подсчета переключения контекста, который уже находится в ядре.

системный вызов wait3 или системный вызов getrusage уже сообщает количество переключений контекста в 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» в исходных кодах ядра, вы можете найти этот accumulate_thread_rusage в kernel/sys.c, который обновляет структуру rusage. Читается от struct task_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;

Затем вы должны найти nvcsw и nivcsw в папке ядра, чтобы узнать, как они обновляются ядром.

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 взят из строки 4091 или строка 4111 того же файла.

PS: отличная ссылка от perreal: http://oreilly.com/catalog/linuxkernel/chapter/ch10.html (поиск context_swtch)

person osgx    schedule 16.02.2012

Это уже существует: виртуальный файл /proc/NNNN/status (где NNNN — десятичный идентификатор процесса, о котором вы хотите узнать) содержит, среди прочего, количество как добровольных, так и непроизвольных переключений контекста. В отличие от getrusage, это позволяет узнать количество переключений контекста для любого процесса, а не только дочернего. Дополнительные сведения см. на proc(5) man-странице. .

person zwol    schedule 16.02.2012

Процесс произведет переключение контекста в случае блокировки, истечения кванта времени или прерывания и т. д. В конце концов вызывается функция 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);
}  
person Deepak    schedule 16.02.2012

Общее количество переключений контекста

cat /proc/PID/sched|grep nr_switches

Добровольное переключение контекста

cat /proc/PID/sched | grep nr_voluntary_switches

Непроизвольное переключение контекста

cat /proc/PID/sched|grep nr_involuntary_switches

где PID — это идентификатор процесса, который вы хотите отслеживать.

Однако, если вы хотите получить эту статистику путем исправления (создания хука) исходного кода linux, код, связанный с планированием, присутствует в

ядро/расписание/

папка исходного дерева. Особенно

kernel/sched/core.c содержит функцию schedule(), которая является кодом планировщика Linux. Код CFS (полностью честный планировщик), который является одним из нескольких планировщиков, присутствующих в Linux, и наиболее часто используемый, представлен в

/kernel/sched/fair.c

scheduler() выполняется всякий раз, когда установлен флаг TIF_NEED_RESCHED, поэтому выясните, из каких мест устанавливается этот флаг (используйте cscope для источника Linux), что даст вам представление о типах переключений контекста, происходящих для процесса.

person Sahil Singh    schedule 30.03.2015