我想限制应用程序的CPU使用率,因为我使用的是Job Objects。基本思想是使用JOB_OBJECT_LIMIT_JOB_TIME
和JOB_OBJECT_POST_AT_END_OF_JOB
在100毫秒的CPU时间后获取通知,然后采取适当的措施。但是我会在1s或2s或3s之后收到通知。通知没有一致性。我使用的基本代码如下:
jobinfo.jobHandle = CreateJobObject(NULL, jobname);
ZeroMemory(&basicLimit, sizeof(basicLimit));
basicLimit.PriorityClass = NORMAL_PRIORITY_CLASS;
basicLimit.LimitFlags = JOB_OBJECT_LIMIT_JOB_TIME;
/* miliseconds in 100-ns intervals */
basicLimit.PerJobUserTimeLimit.QuadPart = timeinmilisecs * 10000;
SetInformationJobObject(jobinfo.jobHandle, JobObjectBasicLimitInformation,
&basicLimit, sizeof(basicLimit))
/* Associate end of job action, so that notification can be generated. */
eojInfo.EndOfJobTimeAction = JOB_OBJECT_POST_AT_END_OF_JOB;
if (!SetInformationJobObject(jobinfo.jobHandle, JobObjectEndOfJobTimeInformation,
&eojInfo, sizeof(eojInfo))
此后,有一个代码可以关联I / O端口并在单独的线程上获取通知。
要收到通知,我使用GetQueuedCompletionStatus()
,然后在收到JOB_OBJECT_MSG_END_OF_JOB_TIME
后再次设置JOB_OBJECT_LIMIT_JOB_TIME
。
您能告诉我为什么中断/通知没有按指定的时间间隔发生吗?
答案 0 :(得分:1)
文档说明了系统标志:
使用PostQueuedCompletionStatus函数将完成数据包发布到完成端口。发布完成数据包后,系统将清除作业结束时间限制,并且作业中的进程可以继续执行。
我认为您可以假设完成数据包已发布。这并不意味着它会立即被拿起来。
看下一步会发生什么:工作中的流程都会继续,好像什么也没发生过一样。如果其中一个运行的优先级高于监视完成端口的线程,则监视线程将饿死,并且将需要一些时间来读取完成状态包。
您应该以与作业任务线程相同或更高的优先级运行该线程,以确保快速获取完成通知。
此外,您应该了解完成数据包仅发送一次。在此之后,根据文档清除了限制。如果重置限制,则仅发送进一步通知。与此同时,流程将继续运行,并且不会有任何限制。
您还应该知道,通知不会根据时钟时间发送,而是根据 处理器使用情况 发送。如果作业使用的是小处理器,则可能需要几秒钟才能使用100毫秒的处理器时间。例如,如果进程正在等待磁盘,用户输入,网络活动或来自其他进程的输入,那么它将不使用处理器,因此这次不会计入限制。