Nós de dispositivo e pilhas de dispositivos

No Windows, os dispositivos são representados por nós de dispositivo na árvore de dispositivos Plug and Play (PnP). Normalmente, quando uma solicitação de E/S é enviada a um dispositivo, vários drivers ajudam a lidar com a solicitação. Cada um desses drivers está associado a um objeto de dispositivo e os objetos de dispositivo são organizados em uma pilha. A sequência de objetos de dispositivo junto com seus drivers associados é chamada de pilha de dispositivos. Cada nó de dispositivo tem sua própria pilha de dispositivos.

Nós de dispositivo e a árvore de dispositivos Plug and Play

O Windows organiza os dispositivos em uma estrutura de árvore chamada árvore de dispositivos Plug and Play ou simplesmente árvore de dispositivos. Normalmente, um nó na árvore de dispositivos representa um dispositivo ou uma função individual em um dispositivo composto. No entanto, alguns nós representam componentes de software que não têm associação com dispositivos físicos.

Um nó na árvore de dispositivos é chamado de nó de dispositivo. O nó raiz da árvore de dispositivos é chamado de nó de dispositivo raiz. Por convenção, o nó do dispositivo raiz é desenhado na parte inferior da árvore do dispositivo, conforme mostrado no diagrama a seguir.

diagrama da árvore de dispositivos, mostrando nós de dispositivos.

A árvore de dispositivos ilustra as relações pai/filho que são inerentes ao ambiente PnP. Vários dos nós na árvore de dispositivos representam barramentos que têm dispositivos filho conectados a eles. Por exemplo, o nó Barramento PCI representa o barramento PCI físico na placa-mãe. Durante a inicialização, o gerenciador PnP pede ao driver de barramento PCI para enumerar os dispositivos que estão conectados ao barramento PCI. Esses dispositivos são representados por nós filho do nó PCI Bus. No diagrama anterior, o nó Barramento PCI tem nós filho para vários dispositivos conectados ao barramento PCI, incluindo controladores de host USB, um controlador de áudio e uma porta PCI Express.

Alguns dos dispositivos conectados ao barramento PCI são barramentos próprios. O gerenciador PnP pede a cada um desses barramentos para enumerar os dispositivos que estão conectados a ele. No diagrama anterior, podemos ver que o controlador de áudio é um barramento que tem um dispositivo de áudio conectado a ele. Podemos ver que a porta PCI Express é um barramento que tem um adaptador de vídeo conectado a ela, e o adaptador de vídeo é um barramento que tem um monitor conectado a ela.

Se você pensa em um nó como representando um dispositivo ou um barramento, depende do seu ponto de vista. Por exemplo, você pode pensar no adaptador de vídeo como um dispositivo que desempenha um papel fundamental na preparação de quadros que aparecem na tela. No entanto, você também pode pensar no adaptador de vídeo como um barramento capaz de detectar e enumerar monitores conectados.

Objetos de dispositivo e pilhas de dispositivos

Um objeto de dispositivo é uma instância de uma estrutura DEVICE_OBJECT. Cada nó de dispositivo na árvore de dispositivos PnP tem uma lista ordenada de objetos de dispositivo e cada um desses objetos de dispositivo está associado a um driver. A lista ordenada de objetos de dispositivo, juntamente com seus drivers associados, é chamada de pilha de dispositivos para o nó do dispositivo.

Você pode pensar em uma pilha de dispositivos de várias maneiras. No sentido mais formal, uma pilha de dispositivos é uma lista ordenada de pares (objeto de dispositivo, driver). No entanto, em certos contextos, pode ser útil pensar na pilha de dispositivos como uma lista ordenada de objetos de dispositivo. Em outros contextos, pode ser útil pensar na pilha de dispositivos como uma lista ordenada de drivers.

Por convenção, uma pilha de dispositivos tem uma parte superior e uma inferior. O primeiro objeto de dispositivo a ser criado na pilha de dispositivos está na parte inferior e o último objeto de dispositivo a ser criado e anexado à pilha de dispositivos está na parte superior.

No diagrama a seguir, o nó do dispositivo Proseware Gizmo tem uma pilha de dispositivos que contém três pares (objeto de dispositivo, driver). O objeto de dispositivo superior está associado ao AfterThought.sys do driver, o objeto de dispositivo do meio está associado ao Proseware.sys do driver e o objeto de dispositivo inferior está associado ao Pci.sys do driver. O nó Barramento PCI no centro do diagrama tem uma pilha de dispositivos que contém dois pares (objeto de dispositivo, driver) - um objeto de dispositivo associado a Pci.sys e um objeto de dispositivo associado a Acpi.sys.

Diagrama mostrando objetos de dispositivo ordenados em pilhas de dispositivos nos nós Proseware, Gizmo e PCI Device.

Como uma pilha de dispositivos é construída?

Durante a inicialização, o gerenciador PnP solicita ao driver de cada barramento para enumerar dispositivos filho que estão conectados ao barramento. Por exemplo, o gerenciador PnP pede ao driver de barramento PCI (Pci.sys) para enumerar os dispositivos que estão conectados ao barramento PCI. Em resposta a essa solicitação, Pci.sys cria um objeto de dispositivo para cada dispositivo conectado ao barramento PCI. Cada um desses objetos de dispositivo é chamado de objeto de dispositivo físico (PDO). Logo após Pci.sys cria o conjunto de PDOs, a árvore de dispositivos se parece com a mostrada no diagrama a seguir.

Diagrama de objetos de nó PCI e dispositivo físico para dispositivos filho.

O gerenciador PnP associa um nó de dispositivo a cada DOP recém-criado e procura no registro para determinar quais drivers precisam fazer parte da pilha de dispositivos para o nó. A pilha de dispositivos deve ter um (e apenas um) driver de função e pode, opcionalmente, ter um ou mais drivers de filtro. O driver de função é o driver principal para a pilha de dispositivos e é responsável por lidar com solicitações de leitura, gravação e controle de dispositivo. Os drivers de filtro desempenham funções auxiliares no processamento de solicitações de leitura, gravação e controle de dispositivo. À medida que cada função e driver de filtro é carregado, ele cria um objeto de dispositivo e se conecta à pilha de dispositivos. Um objeto de dispositivo criado pelo driver de função é chamado de objeto de dispositivo funcional (FDO) e um objeto de dispositivo criado por um driver de filtro é chamado de objeto de dispositivo de filtro (Filter DO). Agora, a árvore de dispositivos se parece com este diagrama.

Diagrama de uma árvore de dispositivos mostrando os objetos de filtro, função e dispositivo físico no nó de dispositivo Proseware Gizmo.

No diagrama, observe que em um nó, o driver de filtro está acima do driver de função e, no outro nó, o driver de filtro está abaixo do driver de função. Um driver de filtro que está acima do driver de função em uma pilha de dispositivos é chamado de driver de filtro superior. Um driver de filtro que está abaixo do driver de função é chamado de driver de filtro inferior.

O PDO é sempre o objeto de dispositivo inferior em uma pilha de dispositivos. Isso resulta da maneira como uma pilha de dispositivos é construída. O PDO é criado primeiro e, à medida que objetos de dispositivo adicionais são anexados à pilha, eles são anexados à parte superior da pilha existente.

Observação Quando os drivers para um dispositivo são instalados, o instalador usa informações em um arquivo de informações (INF) para determinar qual driver é o driver de função e quais drivers são filtros. Normalmente, o arquivo INF é fornecido pela Microsoft ou pelo fornecedor do hardware. Depois que os drivers para um dispositivo são instalados, o gerenciador PnP pode determinar a função e filtrar drivers para o dispositivo procurando no registro.

Motoristas de ônibus

No diagrama anterior, você pode ver que o driver Pci.sys desempenha duas funções. Primeiro, Pci.sys está associado ao FDO no nó do dispositivo PCI Bus. Na verdade, ele criou o FDO no nó do dispositivo PCI Bus. Portanto, Pci.sys é o driver de função para o barramento PCI. Em segundo lugar, Pci.sys está associado à DOP em cada filho do nó Barramento PCI. Lembre-se de que ele criou as DOPs para os dispositivos filho. O driver que cria o PDO para um nó de dispositivo é chamado de driver de barramento para o nó.

Se o seu ponto de referência é o barramento PCI, então Pci.sys é o driver de função. Mas se o seu ponto de referência é o dispositivo Proseware Gizmo, então Pci.sys é o motorista do ônibus. Essa função dupla é típica na árvore de dispositivos PnP. Um motorista que serve como motorista de função para um ônibus também serve como motorista de ônibus para um dispositivo filho do ônibus.

Pilhas de dispositivos no modo de usuário

Até agora, temos discutido pilhas de dispositivos no modo kernel. Ou seja, os drivers nas pilhas são executados no modo kernel, e os objetos de dispositivo são mapeados para o espaço do sistema, que é o espaço de endereço que está disponível apenas para o código em execução no modo kernel. Para obter informações sobre a diferença entre o modo kernel e o modo de usuário, consulte Modo de usuário e modo de kernel.

Em alguns casos, um dispositivo tem uma pilha de dispositivos de modo de usuário, além de sua pilha de dispositivos de modo kernel. Os drivers de modo de usuário geralmente são baseados no UMDF (User-Mode Driver Framework), que é um dos modelos de driver fornecidos pelo WDF (Windows Driver Frameworks). No UMDF, os drivers são DLLs de modo de usuário e os objetos de dispositivo são objetos COM que implementam a interface IWDFDevice. Um objeto de dispositivo em uma pilha de dispositivos UMDF é chamado de objeto de dispositivo WDF (WDF DO).

O diagrama a seguir mostra o nó do dispositivo, a pilha de dispositivos no modo kernel e a pilha de dispositivos no modo usuário para um dispositivo USB-FX-2. Os drivers nas pilhas de modo de usuário e modo kernel participam de solicitações de E/S direcionadas ao dispositivo USB-FX-2.

diagrama mostrando pilhas de dispositivos no modo de usuário e no modo kernel.

Conceitos para todos os desenvolvedores de drivers

Pilhas de drivers