Очень упрощенно, это может работать примерно так:
- Создать периодический таймер ожидания с небольшим разумным временем ожидания (возможно, 100 мс).Получите «последнее» значение для каждого соответствующего процесса, вызывая
GetProcessTimes
один раз. - Цикл навсегда, блокировка по таймеру.
- Каждый раз, когда вы просыпаетесь:
- , если
GetProcessAffinityMask
возвращает 0, позвоните SetProcessAffinityMask(old_value)
.Это означает, что мы приостановили этот процесс в нашей последней итерации, и теперь мы даем ему возможность запустить его снова. - еще вызов
GetProcessTimes
для получения «текущего» значения - вызов
GetSystemTimeAsFileTime
- вычисление дельты путем вычитания последнего из текущего
cpu_usage = (deltaKernelTime + deltaUserTime) / (deltaTime)
- если это больше, чем вы хотите позвоните
old_value = GetProcessAffinityMask
, а затем SetProcessAffinityMask(0)
, что переведет процесс в автономный режим.
Это в основном очень примитивная версия планировщика, работающая в ядре, реализованная в пользовательском пространстве.Он помещает процесс в «спящий режим» на небольшое время, если он использует больше процессорного времени, чем вы считаете правильным.Было бы возможно более сложное измерение, которое может длиться более секунды или 5 секунд (и, вероятно, желательно).
Вместо этого может возникнуть искушение приостановить все потоки в процессе.Тем не менее, важно , а не , чтобы играть с приоритетами, а , а не , чтобы использовать SuspendThread
, если вы точно не знаете, что делает программа, поскольку это может легко привести к тупикам и другой неприятной стороне.последствия.Подумайте, например, о приостановке потока, содержащего критическую секцию, в то время как другой поток все еще работает и пытается получить тот же объект.Или представьте, что ваш процесс обменивается во время приостановки дюжины потоков, в результате чего половина из них работает, а другая половина становится мертвой.
С другой стороны, установка нулевой маски соответствия просто означает, что отныне нетодин поток в процессе получает больше временных интервалов на любом процессоре.Сброс сродства дает - атомарно, одновременно - всем потокам возможность запустить снова.
К несчастью, SetProcessAffinityMask
не возвращает старую маску, как SetThreadAffinityMask
, по крайней мере, согласнодокументация.Поэтому требуется дополнительный Get...
звонок.