Подтвердить что ты не робот

EnumProcesses() vs CreateToolhelp32Snapshot()

Мне было интересно, есть ли какие-либо различия - в основном, с точки зрения производительности - между двумя функциями Win32 API EnumProcesses() и CreateToolhelp32Snapshot() для перечисления всех активных процессов и загруженных модулей. Или если кто-то лучше другого и почему.

4b9b3361

Ответ 1

Я думаю, что они почти одинаковы с точки зрения производительности (и результатов), поскольку оба они называют один и тот же базовый NT API, хотя CreateToolhelp32Snapshot() может иметь небольшие накладные расходы, поскольку он создает объект раздела и копирует всю информацию в в то время как EnumProcesses()/EnumProcessModules() работает непосредственно с пользовательскими буферами. Разница, вероятно, незначительна в реальных действиях, однако.

Я немного предпочитаю EnumProcesses(), поскольку это (IMO) более простой API для использования, но CreateToolhelp32Snapshot() возвращает больше информации, если вам это нужно. Единственным недостатком EnumProcesses() является то, что вы должны вызывать его в цикле, так как вы, возможно, не выделили достаточно большой буфер; CreateToolhelp32Snapshot() берет на себя управление буфером. На практике я просто выделяю буфер в стеке, достаточно большой для хранения 1024 идентификаторов процессов или дескрипторов модулей; до сих пор я не сталкивался с системой, где любой из этих ограничений был даже удаленно близок к достижению. Конечно, мы сказали то же самое о MAX_PATH не так давно, и теперь мы сталкиваемся с проблемами с этим...

Ответ 2

Ниже приведены результаты нескольких функций:

  • EnumProcesses: 16 мс, 207 процессов
  • CreateToolhelp32Snapshot: 141 мс (16 мс), 207 процессов
  • WTSEnumerateProcesses: 16 мс, 207 процессов
  • WTSEnumerateProcessesEx (WTS_CURRENT_SESSION): 16 мс, 98 процессов
  • WTSEnumerateProcessesEx (WTS_ANY_SESSION): 16 мс, 207 процессов

Машина работает под управлением Windows 8 с включенным UAC, пользователь не повышен (например, не имеет доступа к системным процессам). Основной процесс 32-разрядный, машина 64-битная, поэтому много 64-битных процессов вокруг. Есть: сеанс 0 для системы, сеанс 1 для текущего пользователя консоли, сеанс 2 для другого пользователя с быстрым переключением. 207 процессов (это 32- и 64-разрядные, включая псевдо-системный)). 207 также подтверждается Process Explorer. Среди этих 207 процессов: 23 процесса для сеанса 2, 98 процессов - для сеанса 1, а остальные - для сеанса 0.

Результаты для цикла из 10 вызовов одной функции. Они воспроизводятся на 100% при каждом запуске.

Для CreateToolhelp32Snapshot основным результатом является вызов CreateToolhelp32Snapshot, а второй результат (в скобках) - это цикл с First/Next.

Я думаю, что люди путают "перечислять все процессы" (получить PID) и "получить имя процесса /exe ". Первый ( "enumerate" ) не имеет проблем с перекрестностью x32/x64. Но у последнего ( "получить имя" ) есть проблемы - не каждый метод будет работать через x32/x64.

Ответ 3

Я точно не помню, но в отличие от CreateToolhelp32Snapshot(), EnumProcesses() имеет одно из двух или обоих ограничений:  1. Не перечисляет 64-битные процессы, если вызывается из 32-разрядного процесса на x64 OS.  2. Не перечисляет повышенные процессы в Vista и Win7.

Ответ 4

CreateToolhelp32Snapshot FTW. EnumProcesses не перечисляет все системные процессы, как все экземпляры svchost.exe, по крайней мере, на Win XP.

Ответ 5

IMO ключевое различие заключается в требованиях к привилегиям. Я видел случаи, в которых EnumProcesses() терпит неудачу, но CreateToolhelp32Snapshot() работает отлично.

Итак, мне нужно было написать код, который бы обнаружил определенный процесс в системе и соответствующим образом отреагировал. Я написал его с помощью EnumProcesses(), и он отлично работал на моей машине, но не на машинах тестеров. Я просто переписал его с помощью CreateToolhelp32Snapshot(), и я больше не слышал о каких-либо проблемах с ним.