2008-11-19 19 views

Respuesta

20

La información relevante parece estar un poco dispersa en comparación con la documentación habitual de MS. Hay este libro blanco que discute I/O Prioritization in windows. Este documento parece tener indicadores beta por todas partes, pero supongo que probablemente sea bastante preciso.

Dos cosas importantes a tener en cuenta:

  1. Sólo puede reducir la prioridad de las solicitudes IO debajo de lo normal.
  2. El controlador puede ignorar cualquier solicitud y tratarla como normal de todos modos.

Las API útiles para aplicaciones de cliente son SetFileInformationByHandle:

FILE_IO_PRIORITY_HINT_INFO priorityHint; 
priorityHint.PriorityHint = IoPriorityHintLow; 
result = SetFileInformationByHandle(hFile, 
            FileIoPriorityHintInfo, 
            &priorityHint, 
            sizeof(PriorityHint)); 

SetPriorityClass:

// reduce CPU, page and IO priority for the whole process 
result = SetPriorityClass(GetCurrentProcess(), 
          PROCESS_MODE_BACKGROUND_BEGIN); 
// do stuff 
result = SetPriorityClass(GetCurrentProcess(), 
          PROCESS_MODE_BACKGROUND_END); 

SetThreadPriority que es similar:

// reduce CPU, page and IO priority for the current thread 
SetThreadPriority(GetCurrentThread(), THREAD_MODE_BACKGROUND_BEGIN); 
// do stuff 
SetThreadPriority(GetCurrentThread(), THREAD_MODE_BACKGROUND_END); 

SetFileBandwithReservation:

// reserve bandwidth of 200 bytes/sec 
result = SetFileBandwidthReservation(hFile, 
            1000, 
            200, 
            FALSE, 
            &transferSize, 
            &outstandingRequests); 

Para .Net haga las cosas habituales con P/Invoke.

+3

(Sólo se puede reducir la prioridad de las solicitudes IO debajo de lo normal.) Ahora undestand qué ProcessExplorer solamente tiene prioridad normal y baja de E/S. Gracias por la buena respuesta ... – erdogany

13

Parece que la forma "real" de establecer la prioridad de IO de un proceso es utilizando NtSetInformationProcess con la clase de información ProcessIoPriority. Lamentablemente, esta API no está documentada, pero puede verla en acción al adjuntar un depurador a taskeng.exe y romper en ExeTask::GetYourPrioritiesStraight.

creo que el valor PROCESS_INFORMATION_CLASS para ProcessIoPriority es 33 (0x21), y los valores de prioridad son las siguientes:

Very Low: 0 
Low: 1 
Normal: 2 
High: 3 or above? 

Los valores anteriores son una mejor suposición basada en lo que puedo decir desde el depurador; el planificador de tareas parece usar un valor de 1 para tareas con prioridad 7 y un valor de 2 para tareas con prioridad 5 (consulte this question y this MSDN article para obtener más información sobre las prioridades del planificador de tareas). Llamando SetPriorityClass con PROCESS_MODE_BACKGROUND_BEGIN utiliza un valor de 0.

he lamentablemente no se encuentra ninguna API pública que se puede utilizar para esto, que no sea el método SetPriorityClass en respuesta @ 1800 de información, que establece la prioridad a muy bajo.

Editar: He escrito una utilidad que se puede usar para consultar o establecer la prioridad IO de un proceso, available here.

1

Apenas una actualización para esto - que todo se puede hacer a través de .NET sin recurrir a la API de Windows ...

// Set the current process to run at 'High' Priority 
System.Diagnostics.Process process = System.Diagnostics.Process.GetCurrentProcess(); 
process.PriorityClass = System.Diagnostics.ProcessPriorityClass.High; 

// Set the current thread to run at 'Highest' Priority 
Thread thread = System.Threading.Thread.CurrentThread; 
thread.Priority = ThreadPriority.Highest; 

he probado el anterior establecimiento de la prioridad del proceso en una aplicación WPF y funciona bien . No he necesitado configurar la prioridad de subprocesos.

EDITAR: lo anterior se refiere a la prioridad de CPU de un proceso, en oposición a la prioridad de E/S; sin embargo, puede haber alguna correlación/conexión entre la prioridad de CPU de un proceso y su prioridad de E/S.

+0

No parece haber un equivalente de .NET de SetFileInformationByHandle para cambiar la prioridad de IO, sin embargo, como se señala en 1800 INFORMATION, esta API solo le permite reducir la prioridad a menos de lo normal. – eodabash

+1

¿no es esta la prioridad de la CPU, no la prioridad de IO? – CodesInChaos

+0

@CodeInChaos sí, tienes razón, aunque imaginas que habría alguna conexión entre la prioridad de la CPU de un proceso y su prioridad de E/S? –

4

La forma correcta de hacer esto es llamar SetProcessPriorityClass con PROCESS_BACKGROUND_MODE_BEGIN para iniciar un segundo plano. Esto causa una prioridad de E/S muy baja (fondo) y una prioridad de CPU inactiva. Cuando termine, vuelva a llamar a SetProcessPriorityClass, proporcionando PROCESS_BACKGROUND_MODE_END. Lo mismo se puede hacer en el nivel de subproceso a través de SetThreadPriority y THREAD_BACKGROUND_MODE_BEGIN/END.

Si desea establecer directamente la prioridad de E/S, independientemente de la prioridad de la CPU, debe utilizar las API nativas NT. Lo documenté here, pero no incluí ejemplos de código, ya que todos sabemos que se copiaron al pie de la letra.

La API que desea es la API NT nativa NtSetInformationProcess. Al usar esta API puede cambiar la prioridad de E/S. Esta API acepta una variable de 'clase' que le dice qué tipo de información sobre el proceso desea cambiar, esa variable de clase debe establecerse en ProcessIoPriority. A continuación, puede configurar la prioridad de E/S del proceso de esta manera.

De forma similar, la prioridad de E/S se puede recuperar a través de NtQueryInformationProcess.

La mala noticia es que los niveles de prioridad son un poco limitados. Critical está reservado para las operaciones de paginación del sistema. Eso lo deja con Normal y Muy bajo (fondo). Bajo y Alto pueden o no implementarse en ediciones más nuevas de Windows. Parece haber un apoyo parcial, por lo menos.

Si no tiene experiencia con las API NT Native, lo primero que debe hacer es entenderlas. Una vez que lo hagas, verás que es tan simple como una sola llamada API.

+1

El artículo que ha vinculado afirma que establecer la clase de prioridad de un proceso afecta su prioridad de E/S. No puedo encontrar ninguna documentación de Microsoft que indique este hecho. Además, mi prueba revela que simplemente no es el caso. Al establecer la clase de prioridad en 'Inactivo' en un proceso, parece que NO cambia su prioridad de E/S. – AlexPi

+0

La forma en que Microsoft terminó haciendo esto es a través de SetProcessPriorityClass y/o SetThreadPriority, lo que indica un 'modo de fondo'. Esto hace que Windows ajuste tanto la prioridad de la CPU (al reposo) como la prioridad de E/S (a fondo) en un nivel de proceso, o nivel de subproceso, respectivamente. –

2

Asegúrese de alinear correctamente la estructura FILE_IO_PRIORITY_HINT_INFO al llamar al SetFileInformationByHandle.

De lo contrario, obtendrá un ERROR_NOACCESS (error 998, 0x000003E6).

_declspec(align(8)) FILE_IO_PRIORITY_HINT_INFO priorityHint; 
priorityHint.PriorityHint = IoPriorityHintLow; 

BOOL ret = SetFileInformationByHandle(hFile, FileIoPriorityHintInfo, &priorityHint, sizeof(FILE_IO_PRIORITY_HINT_INFO)); 
DWORD err = GetLastError(); 
Cuestiones relacionadas