Мне нужно сделать системный вызов, чтобы подсчитать добровольные и непроизвольные переключения контекста процесса. Я уже знаю шаги по добавлению нового системного вызова в ядро 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-странице. .
Процесс произведет переключение контекста в случае блокировки, истечения кванта времени или прерывания и т. д. В конце концов вызывается функция 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);
}
Общее количество переключений контекста
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), что даст вам представление о типах переключений контекста, происходящих для процесса.