Как получить тактовые частоты процессора, используемые процессом в режиме ядра на Windows?

Как следует из названия, я заинтересован в получении тактовых циклов процессора, используемых процессом только в режиме ядра. Я знаю, что есть API под названием «QueryProcessCycleTime», который возвращает часы процессора
циклы, используемые потоками процесса. Но это значение включает циклы, проведенные как в режиме пользователя, так и в режиме ядра. Как я могу получить циклы, проведенные только в режиме ядра? Нужно ли получать это с помощью счетчиков производительности? Если да, какой я должен использовать?

Заранее спасибо за ваши ответы.

1

Решение

Я только что нашел интересную статью, которая описывает почти то, что вы просите. Это на MSDN Internals.

Там пишут, что если вы использовали C # или C ++ / CLI, вы можете легко получить эту информацию из экземпляра System.Diagnostic.Process класс, указал на правильный PID. Но это даст вам TimeSpan от PrivilegedProcessorTimeтак что «красивое время» вместо «циклов».

Тем не менее, они также указывают, что весь этот .Net-код на самом деле является тонкой оболочкой для неуправляемых API, поэтому вы также можете легко получить его из нативного C ++. Они использовали ILDASM для показа того, что он называет, но изображение отсутствует. Я только что сделал то же самое, и он использует GetProcessTimes от kernel32.dll

Итак, еще раз, MSDN’инг это — это возвращается LPFILETIME структур. Итак, снова «красивое время», а не «циклы».

Описание этого метода указывает на то, что если вы хотите получить тактовые циклы, вы должны использовать QueryProcessCycleTime функция. Это на самом деле возвращает количество тактов … но пользовательский режим и режим ядра подсчитываются вместе.

Теперь подводим итоги:

  • Вы можете прочитать userTIME
  • вы можете прочитать kernelTIME
  • Вы можете прочитать (пользователь + ядро) ЦИКЛЫ

Таким образом, у вас есть почти все необходимое. По простой математике:

u_cycles = u_time * allcycles / (utime+ktime)
k_cycles = k_time * allcycles / (utime+ktime)

Конечно, это будет некоторое приближение из-за округления и т. Д.

Кроме того, здесь есть недочёт: вам нужно вызвать две функции (GetTimes, QueryCycles), чтобы получить всю информацию, поэтому между их показаниями будет небольшая задержка и, следовательно, весь ваш расчет. вероятно, немного поскользнется поскольку целевой процесс все еще выполняется и сжигает время.

Если вы не можете учесть этот (маленький?) Шум в измерении, я думаю, что вы можете обойти его временно суспендирующий процесс:

  • приостановить цель
  • подождите немного и убедитесь, что он приостановлен
  • читать первую статистику
  • читать вторую статистику
  • затем возобновите процесс и рассчитайте значения

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

Возможно, есть какой-то лучший способ получить отдельные тактовые циклы, но я их не нашел, извините. Вы можете попробовать заглянуть внутрь QueryProcessCycleTime и из какого источника он читает данные — может быть, вам повезло, и он читает A, B и возвращает A + B, и, возможно, вы можете посмотреть, какие источники. Я не проверял это.

2

Другие решения

Взгляни на GetProcessTimes. Это даст вам количество ядра и пользовательское время, использованное вашим процессом.

1