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

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

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)

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

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

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), что даст вам представление о типах переключений контекста, происходящих в процессе.

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