Configuration et utilisation de files d’attente d’appareils
Un pilote configure un objet de file d’attente de périphérique en appelant KeInitializeDeviceQueue lors de l’initialisation du pilote ou du périphérique. Après avoir démarré ses périphériques, le pilote insère des irps dans cette file d’attente en appelant KeInsertDeviceQueue ou KeInsertByKeyDeviceQueue. La figure suivante illustre ces appels.
Comme le montre cette figure, le pilote doit fournir le stockage d’un objet de file d’attente de périphérique, qui doit être résident. Les pilotes qui configurent un objet de file d’attente de périphérique fournissent généralement le stockage nécessaire dans l’extension de périphérique d’un objet de périphérique créé par le pilote, mais le stockage peut se trouver dans une extension de contrôleur si le pilote utilise un objet contrôleur ou dans un pool non paginé alloué par le pilote.
Si le pilote fournit du stockage pour l’objet de file d’attente de périphérique dans une extension de périphérique, il appelle KeInitializeDeviceQueue après avoir créé l’objet de périphérique et avant de démarrer l’appareil. En d’autres termes, le pilote peut initialiser la file d’attente à partir de sa routine AddDevice ou lorsqu’il gère une demande de IRP_MN_START_DEVICE PnP. Dans l’appel à KeInitializeDeviceQueue, le pilote passe un pointeur vers le stockage qu’il fournit pour l’objet de file d’attente de périphérique.
Après avoir démarré ses appareils, le pilote peut insérer un IRP dans sa file d’attente de périphériques en appelant KeInsertDeviceQueue, qui place l’IRP à la fin de la file d’attente, ou KeInsertByKeyDeviceQueue, qui place l’IRP dans la file d’attente en fonction d’une valeur SortKey déterminée par le pilote, comme indiqué dans la figure précédente.
Chacune de ces routines de prise en charge retourne une valeur booléenne indiquant si l’IRP a été inséré dans la file d’attente. Chacun de ces appels définit également l’état de l’objet file d’attente de l’appareil sur Occupé si la file d’attente est actuellement vide (Non occupé). Toutefois, si la file d’attente est vide (Non occupé), ni la routine KeInsertXxxDeviceQueue n’insère l’IRP dans la file d’attente. Au lieu de cela, il définit l’état de l’objet file d’attente d’appareils sur Occupé et retourne FALSE. Étant donné que l’IRP n’a pas été mis en file d’attente, le pilote doit le transmettre à une autre routine de pilote pour un traitement ultérieur.
Lorsque vous configurez des files d’attente d’appareils supplémentaires, suivez ces instructions d’implémentation :
Lorsqu’un appel à KeInsertXxxDeviceQueue retourne FALSE, l’appelant doit transmettre l’IRP qu’il a tenté de mettre en file d’attente pour un traitement ultérieur à une autre routine de pilote. Toutefois, l’appel à KeInsertXxxDeviceQueue change l’état de l’objet de file d’attente d’appareil en Occupé. Ainsi, le IRP suivant à entrer est inséré dans la file d’attente, sauf si le pilote appelle d’abord KeRemoveXxxDeviceQueue .
Lorsque l’état de l’objet file d’attente d’appareil est défini sur Occupé, le pilote peut supprimer une IRP pour un traitement ultérieur ou réinitialiser l’état à Not-Busy en appelant l’une des routines de support suivantes :
KeRemoveDeviceQueue pour supprimer l’IRP en tête de la file d’attente
KeRemoveByKeyDeviceQueue pour supprimer un IRP choisi en fonction d’une valeur SortKey déterminée par le pilote
KeRemoveEntryDeviceQueue pour supprimer un IRP particulier dans la file d’attente ou pour déterminer si un IRP particulier se trouve dans la file d’attente
KeRemoveEntryDeviceQueue retourne une valeur booléenne indiquant si l’IRP se trouvait dans la file d’attente de l’appareil.
L’appel de l’une de ces routines pour supprimer une entrée d’une file d’attente d’appareil vide, mais Occupé modifie l’état de la file d’attente sur Non occupé.
Chaque objet de file d’attente d’appareil est protégé par un verrou de rotation exécutif intégré (non indiqué dans la figure Utilisation d’un objet file d’attente d’appareils ). Par conséquent, un pilote peut insérer des irps dans la file d’attente et les supprimer de manière sécurisée multiprocesseur de toute routine de pilote s’exécutant à une valeur inférieure ou égale à IRQL = DISPATCH_LEVEL. En raison de cette restriction IRQL, un pilote ne peut pas appeler une routine KeXxxDeviceQueue à partir de ses routines ISR ou SynchCritSection , qui s’exécutent sur DIRQL.
Pour plus d’informations, consultez Gestion des priorités matérielles et des verrous de rotation. Pour connaître les exigences IRQL pour une routine de support spécifique, consultez la page de référence de la routine.