winapi - Hvordan begrænser du en proces 'CPU-brug på Windows? (brugskode, ikke en app)

Indlæg af Hanne Mølgaard Plasc

Problem



Der er programmer, der kan begrænse CPU-brugen af ​​processer i Windows. For eksempel BES og ThreadMaster. Jeg skal skrive mit eget program, der gør det samme som disse programmer, men med forskellige konfigurationsfunktioner. Er der nogen, der ved, hvordan CPU-gasstrømningen af ​​en proces er færdig (kode)? Jeg snakker ikke om at prioritere en proces, men hvordan man begrænser den til CPU-brugen til f.eks. 15\%, selv om der ikke er andre processer, der konkurrerer om CPU-tid. [15] [16]


Opdatering: Jeg skal kunne sprede alle processer, der allerede kører, og at jeg ikke har adgang til kildekoden til.

Bedste reference


Meget forenklet, det kunne fungere på en eller anden måde som dette:



  1. Opret en periodisk ventetimer med en rimelig rimelig ventetid (måske 100ms). Få en 'sidste' værdi for hver relevant proces ved at ringe GetProcessTimes én gang.

  2. Loop forever, blokering på timeren.

  3. Hver gang du vågner op:

    • hvis GetProcessAffinityMask returnerer 0, ring til SetProcessAffinityMask(old\_value). Det betyder, at vi har suspenderet den proces i vores sidste iteration, vi giver nu en chance for at køre igen.

    • ellers ring til GetProcessTimes for at få den aktuelle værdi

    • ring til GetSystemTimeAsFileTime

    • Beregn delta ved at trække sidste fra nuværende

    • cpu\_usage = (deltaKernelTime + deltaUserTime) / (deltaTime)

    • hvis det er mere end du vil ring til old\_value = GetProcessAffinityMask efterfulgt af SetProcessAffinityMask(0), som vil tage processen offline.




Dette er dybest set en meget primitiv version af planlæggeren, der kører i kernen, implementeret i brugerland. Det sætter en proces 'at sove' i lidt tid, hvis den har brugt mere CPU-tid end hvad du finder rigtig. En mere sofistikeret måling måske gå over et sekund eller 5 sekunder ville være muligt (og sandsynligvis ønskeligt).


Du kan måske være fristet til at suspendere alle tråde i processen i stedet. Det er dog vigtigt ikke at fyre med prioriteter og ikke for at bruge SuspendThread, medmindre du ved præcis, hvad et program gør, da det let kan føre til deadlocks og andre ubehagelige bivirkninger. Tænk for eksempel på at suspendere en tråd med en kritisk sektion, mens en anden tråd stadig kører og forsøger at erhverve det samme objekt. Eller forestil dig, at din proces bliver byttet i midten af ​​at suspendere et dusin tråde, så halvdelen af ​​dem løber og den anden halvdel er død.


Indstilling af affinitetsmasken til nul på den anden side betyder simpelthen, at ingen enkelt tråd i processen hidtil får flere tidsskiver på enhver processor. Nulstilling af affiniteten giver - atomisk samtidig - alle tråde muligheden for at løbe igen.


Uheldigvis returnerer SetProcessAffinityMask ikke den gamle maske som SetThreadAffinityMask gør, i det mindste ifølge dokumentationen. Derfor er et ekstra Get... opkald nødvendigt.

Andre referencer 1


Du vil sandsynligvis køre processen (e) i et jobobjekt og indstille den maksimale CPU-brug for jobobjektet med SetInformationJobObject, med JOBOBJECT\_CPU\_RATE\_CONTROL\_INFORMATION. [17] [18]

Andre referencer 2


CPU-brugen er ret simpel at estimere ved hjælp af QueryProcessCycleTime. Maskinens processorhastighed kan hentes fra HKLM \ HARDWARE \ DESCRIPTION \ System \ CentralProcessor \\ ~ MHz (hvor er processorenummeret, en post for hver processor til stede). Med disse værdier kan du estimere din proces 'CPU-brug og giv CPU'en som nødvendigt ved hjælp af Sleep () for at holde din brug i grænse. [19]