Как вы уже, наверное, заметили, я всегда хочу быть в курсе того, что делает моя система. Я хочу знать, вызывает ли процесс загрузку процессора, что, в свою очередь, приводит к загрузке памяти или чтению с диска.
Это позволяет мне поддерживать работу компьютеров в нормальном режиме, но иногда мое любопытство помогает мне в значительной степени увеличить производительность и избавиться от некоторых проблем в Windows и сторонних приложениях.
Основной инструмент, который я использую в своей работе, - это Process Explorer, настроенный на автоматический запуск при моем входе в систему. Всякий раз, когда я осуществляю первоначальную настройку нового компьютера, я добавляю ссылку на Process Explorer в папку Start в своем профиле, используя ключ /t, который запускает программу в свернутом режиме. Таким образом, Process Explorer при запуске сразу сворачивается в трей. Для получения полного доступа к своим и системным процессам, в Vista я использую ключ /e, которой при загрузке Windows вызывает диалог подтверждения UAC и дает гарантию, что Process Explorer обладает административными правами.
Так как я слежу за уровнем загрузки процессора по иконке Process Explorer в трее (системные процессы отображаются красным цветом, а пользовательские - зеленым), то за последние несколько месяцев я уже обнаружил несколько ошибок. В данном посте я расскажу, как с помощью Process Explorer и другого инструмента, Kernrate, идентифицировать проблемы со сторонними драйверами и проблемами, к которым они могут привести.
Вскоре после того как, несколько месяцев назад я получил новый ноутбук, я заметил, что система время от времени начинала сильно тормозить. Иконка Process Explorer в трее подтвердила мои подозрения, отобразив активность загрузки процессора сплошным красным цветом. При наведении курсора мышки на значок программы в трее всплывает подсказка, в которой показано, что именно привело к такой загрузке, и, в данном случае, виноват был процесс System.
Первые несколько раз, когда я сталкивался с проблемой, она исчезала так быстро, что я не успевал с ней разобраться. Однако, открыв System Information в Process Explorer, я обнаружил, что такие загрузки процессора случались довольно часто.
Процесс System отличается тем, что у него нет загружаемого образа, который есть у других процессов. Он существует только для того, чтобы распределять потоки операционной системы по управлению памятью, кэшем, а также другими подсистемами и потоками драйверов. Эти потоки запускаются в рамках режима ядра, вот почему процесс System показывается красным.
Я предположил, что причиной проблемы является драйвер от стороннего производителя, так что первым делом мне необходимо было узнать, какой поток загружал процессор. Я внимательно следил за признаками проблемы каждый раз, когда переходил из сети в сеть, и однажды я столкнулся с такой проблемой. Process Explorer показал, что процесс запущен в потоке на странице Threads в диалоговом окне Process Properties, так что я нажал два раза на процессе System и перешел на страницу Threads, когда в следующий раз увидел скачок потребления процессора.
Префикс ntkrnlpa.exe в начале адреса каждого потока позволил мне определить, что тот процесс, который вызывал загрузку процессора, являлся системным процессом. Ntkrnlpa.exe - версия ядра, загруженная в 32-х битной системе, которая не может использовать защиту памяти, или в серверной системе, которой необходимо обращаться к более, чем 4 Гб памяти. Так как я уже настроил Process Explorer на получение символов для образов операционной системы с публичного сервера символов Microsoft, то в списке потоков также были показаны имена стартовых функций потоков. Самые активные потоки начинались в функции ExpWorkerThread, что значит, что они были исполнителями потока, которые работали от имени системы и драйверов устройств. Вместо того, чтобы создавать отдельные потоки, что вызовет дополнительное потребление памяти, система и драйвера могут переместить работу на общий пул исполнителей потоков операционной системы.
К сожалению, знание того, что исполнители потоков становились причиной потребления мощностей процессора, ничуть не приблизило меня к корню проблемы. Мне необходимо было точно знать, какую именно функцию вызывали исполнители потоков, так как функция могла находиться внутри драйвера устройства или в компоненте операционной системы, от имени которого работал поток. Единственным способом заглянуть в выполнение потока является изучение стека потока с помощью Process Explorer. Стек - область памяти, которая хранит вызов функции на выполнение, и Process Explorer покажет вам стек потока, когда вы выберете поток и нажмете кнопку Stack, или два раза щелкните мышкой. Однако в Vista, когда вы попытаетесь изучить стек потока процесса System, вы увидите ошибку.
Процесс System - специальный тип процессов, которые в Vista называются "защищенными процессами" и которые не разрешают какой-либо доступ к памяти своих потоков. Защищенные процессы были созданы с целью реализации Digital Rights Management (DRM), так чтобы поставщики HD-контента могли хранить ключи дешифровки содержимого с меньшим риском, если пользователь-администратор будет использовать инструменты для снятия DRM-защиты, чтобы проникнуть в процесс и получить ключи.
Поэтому мне пришлось искать другой способ просмотра действий исполнителя потоков. Для этого я обратился к KernRate - профильному приложению для командной строки, которое доступно для бесплатной загрузки с сайта Microsoft. KernRate может профилировать пользовательские процессы и потоки ядра. Программа использует основанные на примерах профильные инструменты, которые были представлены еще в первой версии Windows NT. Эти инструменты записывают уникальные адреса, которые, когда срабатывает профильный таймер, использует процессор. Когда вы прекращаете сбор данных профиля, Kernrate получает информацию о ядре, отображает список адресов для загруженных драйверов и даже может использовать сервер символов для сообщения имени функции.
Так как если бы трассировка идентифицировала драйвер устройства, мне бы не понадобился сервер символов, то я запустил Kernrate без каких либо параметров. Несмотря на тот факт, что версии Kernrate, которая официально поддерживала бы Vista нет, версия для Windows XP, работает и в Vista х86 (также вы можете использовать недавно выпущенную программу xperf для проведения схожих операций профилирования. Данный инструмент работает лишь в Vista или Server 2008, но поддерживает также и х64-редакции операционных систем). Я указал программе адрес к профилю, а потом нажал Ctrl+C, чтобы отобразить результат в окне консоли.
В первой строчке было обращение к ядру, но на второй был драйвер, который я не смог опознать — b57nd60x. Большинство драйверов находятся в папке %systemroot%\system32\drivers, так что я легко мог бы открыть эту папку в Windows Explorer и посмотреть свойства файла там, но у меня уже был открыт Process Explorer, так что легче и быстрее было бы открыть просмотр библиотек процесса System. Просмотр библиотек показывает библиотеки и файлы, размещенные в адресном пространстве пользовательских процессов, но для процесса System показываются модули ядра, включая драйвера, загруженные в системе. Просмотр библиотек показал, что данный драйвер был произведен Broadcom и имел версию 10.10.
Теперь, когда я узнал, что причиной резких скачков использования процессора был драйвер Broadcom, первым шагом было проверить, есть ли новая версия драйвера. Я зашел на страницу загрузки драйверов на сайте Dell, но ничего не нашел. Подозревая, что проблема, которую я обнаружил, могла быть ранее неизвестной, я решил уведомить о ней Broadcom. Я использовал связи здесь, в Microsoft, чтобы найти представителя драйверов от Broadcom, и детально описать ему свои симптомы и результаты исследования. Он переслал мое письмо разработчикам драйверов и они признали, что не знали о существовании проблемы. Через несколько дней они прислали мне отладочную версию драйвера с идентификаторами, так что я мог во время захвата профиля в Kernrate, сообщить разработчикам какая именно функция была активна, во время скачков потребления процессора. Проблема появилась снова через несколько дней, о чем я незамедлительно сообщил разработчикам.
Разработчики объяснили мне, что моя трассировка показала, что драйвер неэффективно работал с шиной PCIe при обработке специфичных запросов, к тому же проблему усугубило используемое мной аппаратное обеспечение. Разработчики предоставили новую версию драйвера и после нескольких недель плотного тестирования я подтвердил, что проблема была решена. Обновленный драйвер еще не был опубликован на сайте Dell, но я думаю, что он там появится в ближайшее время. Закрыто еще одно дело, на этот раз с помощью Process Explorer, Kernrate и разработчиков драйверов Broadcom.