Dê a sua opinião sobre a experiência de download do PDF.
Introdução a drivers no Windows
Artigo • 30/12/2024
Bem-vindo à documentação do Windows Driver! Nesta seção, você aprenderá os
conceitos básicos sobre drivers, os diferentes tipos de drivers e como escrever um
driver.
7 Observação
Para entender os conceitos nesta seção, você já deve estar familiarizado com a
linguagem de programação Ce deve entender as ideias de ponteiros de função,
funções de retorno de chamada e manipuladores de eventos.
Nesta seção
O que é um driver?
Drivers internos
Escolher um modelo de driver
Escreva seu primeiro driver
Do código de exemplo ao driver de produção
Provisionar um computador para implantação e teste de driver (WDK 10)
Conceitos para todos os desenvolvedores de drivers
Tópicos relacionados
Kit de Driver do Windows (WDK)
Diretrizes de segurança do driver
Comentários
Esta página foi útil? Yes No
Fornecer comentários sobre o produto | Obter ajuda no Microsoft Q&A
O que é um motorista?
Artigo • 27/09/2024
Um driver é um componente de software que permite que o sistema operacional e um
dispositivo se comuniquem. Por exemplo, quando um aplicativo precisa ler dados de um
dispositivo, ele chama uma função implementada pelo sistema operacional. Em seguida,
o sistema operacional chama uma função implementada pelo driver. O driver,
geralmente desenvolvido pelo fabricante do dispositivo, sabe como se comunicar com o
hardware do dispositivo para obter os dados. Depois que o driver obtém os dados, ele
os devolve ao sistema operacional, que os devolve ao aplicativo.
Expandindo a definição
Nossa explicação simplifica o conceito de drivers. Aqui estão mais alguns pontos a
serem considerados:
Os drivers nem sempre precisam ser desenvolvidos pelo fabricante do dispositivo.
Se um dispositivo seguir um padrão de hardware publicado, a Microsoft poderá
escrever o driver para que o designer de dispositivos não precise fornecer um.
Nem todos os drivers se comunicam diretamente com um dispositivo. Muitas
vezes, vários drivers em camadas em uma pilha de driver participam de uma
solicitação de E/S. A maneira convencional de visualizar a pilha é com o primeiro
participante na parte superior e o último participante na parte inferior, conforme
mostrado neste diagrama. Alguns drivers na pilha alteram a solicitação de um
formato para outro. Esses drivers não se comunicam diretamente com o
dispositivo. Em vez disso, eles alteram a solicitação e a transmitem para drivers que
estão mais baixos na pilha.
Driver de função: o driver que se comunica diretamente com o dispositivo é
chamado de driver de função.
Driver de filtro: os drivers que fazem o processamento auxiliar são chamados de
drivers de filtro.
Para obter mais informações sobre pilhas, consulte Pilhas de driver.
Alguns drivers de filtro observam e registram informações sobre solicitações de
E/S, mas não participam ativamente delas. Por exemplo, alguns drivers de filtro
atuam como verificadores para garantir que os outros drivers na pilha manipulem
a solicitação de E/S corretamente.
Podemos refinar nossa definição de um driver como qualquer componente de software
que observe ou participe da comunicação entre o sistema operacional e um dispositivo.
Drivers de software
Nossa definição expandida é razoavelmente precisa, mas ainda está incompleta porque
alguns drivers não estão associados a nenhum dispositivo de hardware.
Por exemplo, se você precisar escrever uma ferramenta que acesse as estruturas de
dados principais do sistema operacional, poderá dividir a ferramenta em dois
componentes. O primeiro componente é executado no modo de usuário e apresenta a
interface do usuário. O segundo componente é executado no modo kernel e acessa os
dados principais do sistema operacional. O componente executado no modo de usuário
é chamado de aplicativo e o componente executado no modo kernel é chamado de
driver de software. Um driver de software não está associado a um dispositivo de
hardware.
Este diagrama ilustra um aplicativo de modo de usuário se comunicando com um driver
de software no modo kernel.
Os drivers de software sempre são executados no modo kernel. Eles são gravados
principalmente para acessar dados protegidos disponíveis somente no modo kernel. No
entanto, nem todos os drivers de dispositivo precisam de acesso a dados e recursos no
modo kernel, portanto, alguns drivers de dispositivo são executados no modo de
usuário.
Para obter mais informações sobre modos de processador, consulte Modo de Usuário e
Modo Kernel.
Motoristas de ônibus
Outro tipo de motorista é o motorista do ônibus. Para entender os drivers de ônibus,
você precisa entender os nós do dispositivo e a árvore de dispositivos.
Para obter informações sobre árvores de dispositivo, nós de dispositivo e drivers de
barramento, consulte Nós de dispositivo e pilhas de dispositivos.
Mais informações sobre drivers de função
Nossa explicação até agora simplifica demais a definição do driver de função.
Declaramos que o driver de função de um dispositivo é o único driver na pilha que se
comunica diretamente com o dispositivo. Isso é verdadeiro para um dispositivo que se
conecta diretamente ao barramento PCI (Interconexão de Componentes Periféricos). O
driver de função para um dispositivo PCI obtém endereços mapeados para recursos de
porta e memória no dispositivo. O driver de função se comunica diretamente com o
dispositivo gravando nesses endereços.
No entanto, em muitos casos, um dispositivo não se conecta diretamente ao
barramento PCI. Em vez disso, o dispositivo se conecta a um adaptador de barramento
de host conectado ao barramento PCI. Por exemplo, uma torradeira USB se conecta a
um adaptador de barramento de host (chamado de controlador de host USB), que está
conectado ao barramento PCI. A torradeira USB tem um driver de função e o
controlador de host USB também tem um driver de função. O driver de função para a
torradeira se comunica indiretamente com a torradeira enviando uma solicitação para o
driver de função para o controlador de host USB. O driver de função para o controlador
de host USB se comunica diretamente com o hardware do controlador de host USB, que
se comunica com a torradeira.
Comentários
Esta página foi útil? Yes No
Fornecer comentários sobre o produto | Obter ajuda no Microsoft Q&A
Drivers integrados para dispositivos
Windows
Artigo • 21/12/2024
O Microsoft Windows contém drivers internos para muitos tipos de dispositivos. Se
houver um driver interno para o seu tipo de dispositivo, você não precisará gravar seu
próprio driver. Seu dispositivo pode usar o driver integrado.
Drivers integrados para dispositivos USB
Se o dispositivo pertencer a uma classe de dispositivo definida pelo DWG (Grupo de
Trabalho de Dispositivos USB), talvez já haja um driver de classe USB do Windows
existente para ele. Para obter mais informações, consulte Drivers para as classes de
dispositivo USB com suporte.
Verifique os drivers internos do seu dispositivo
Você pode exibir uma lista de drivers instalados para seu dispositivo e suas
propriedades usando driverquery comando. Para exibir os drivers instalados no
computador local, abra a janela do Prompt de Comando e digite:
Prompt de comando do Windows
driverquery
Para obter mais informações, consulte driverquery.
Comentários
Esta página foi útil? Yes No
Fornecer comentários sobre o produto | Obter ajuda no Microsoft Q&A
Escolha um modelo de driver
Artigo • 29/06/2024
O Microsoft Windows fornece uma variedade de modelos de driver que você pode usar
para gravar drivers. A estratégia para escolher o melhor modelo de driver depende do
tipo de driver que você está planejando escrever. Aqui estão as opções:
Driver de função do dispositivo
Driver de filtro de dispositivo
Driver de software
Driver de filtro do sistema de arquivos
Driver do sistema de arquivos
Para obter uma discussão sobre as diferenças entre os vários tipos de drivers, consulte O
que é um driver? e Nós de dispositivo e pilhas de dispositivos. As seções a seguir
explicam como escolher um modelo para cada tipo de driver.
Escolhendo um modelo de driver para um
driver de função de dispositivo
Ao projetar um dispositivo de hardware, uma das primeiras coisas a considerar é se você
precisa escrever um driver de função. Faça as seguintes perguntas:
Você pode evitar escrever um driver completamente? Se você deve escrever um driver
de função, qual é o melhor modelo de driver para usar? Para responder a essas
perguntas, determine onde seu dispositivo se encaixa na lista de tecnologias descritas
em Tecnologias de dispositivo e driver. Consulte a documentação dessa tecnologia
específica para determinar se você precisa escrever um driver de função e para saber
quais modelos de driver estão disponíveis para seu dispositivo.
Algumas das tecnologias individuais têm modelos minidriver. Em um modelo de
minidriver, o driver de dispositivo consiste em duas partes: uma que lida com tarefas
gerais e outra que lida com tarefas específicas do dispositivo. Normalmente, a Microsoft
grava a parte geral e o fabricante do dispositivo grava a parte específica do dispositivo.
As partes específicas do dispositivo têm uma variedade de nomes, a maioria dos quais
compartilham o prefixo mini. Aqui estão alguns dos nomes usados em modelos de
minidriver:
Exibir driver de miniporta
Driver de miniporta de áudio
Driver de miniclasse de bateria
Driver de protocolo Bluetooth
Minidriver HID
Minidriver WIA
Driver de miniporta NDIS
Driver de miniporta de armazenamento
Minidriver de streaming
Para obter uma visão geral dos modelos de minidriver, consulte Minidrivers e pares de
drivers.
Nem todas as tecnologias listadas em Tecnologias de dispositivos e drivers têm um
modelo de minidriver dedicado. A documentação de uma tecnologia específica pode
aconselhá-lo a usar o Kernel-Mode Driver Framework (KMDF), a documentação de outra
tecnologia pode aconselhá-lo a usar o User-Mode Driver Framework (UMDF). O ponto
chave é que você deve começar estudando a documentação para a tecnologia
específica do seu dispositivo. Se a tecnologia do dispositivo tiver um modelo de
minidriver, você deverá usar o modelo de minidriver. Caso contrário, siga as
recomendações na documentação específica da tecnologia sobre se deve usar o UMDF,
KMDF ou o WDM (Windows Driver Model).
Escolhendo um modelo de driver para um
driver de filtro de dispositivo
Frequentemente, vários drivers participam de uma única solicitação de E/S (como ler
dados de um dispositivo). Os drivers são colocados em camadas em uma pilha, e a
maneira convencional de visualizar a pilha é com o primeiro driver na parte superior e o
último driver na parte inferior. A pilha tem um driver de função e também pode ter
drivers de filtro. Para obter uma discussão sobre drivers de função e drivers de filtro,
consulte O que é um driver? e Nós de dispositivo e pilhas de dispositivos.
Se você estiver se preparando para escrever um driver de filtro para um dispositivo,
determine onde seu dispositivo se encaixa na lista de tecnologias descritas em
Tecnologias de dispositivo e driver. Verifique se a documentação da tecnologia do seu
dispositivo específico tem alguma orientação sobre a escolha de um modelo de driver
de filtro. Se a documentação da tecnologia do dispositivo não oferecer essa orientação,
considere primeiro usar o UMDF como modelo de driver. Se o driver de filtro precisar de
acesso a estruturas de dados que não estão disponíveis por meio do UMDF, considere
usar o KMDF como seu modelo de driver. No caso raro em que seu driver precisa de
acesso a estruturas de dados não disponíveis por meio do KMDF, use o WDM como seu
modelo de driver.
Escolhendo um modelo de driver para um
driver de software
Um driver que não está associado a um dispositivo é chamado de driver de software.
Para obter uma discussão sobre drivers de software, consulte O que é um driver?. Os
drivers de software são úteis porque podem ser executados no modo kernel, o que lhes
dá acesso aos dados protegidos do sistema operacional. Para obter informações sobre
modos de processador, consulte Modo de usuário e modo de kernel.
Para um driver de software, suas duas opções são KMDF e o modelo de driver herdado
do Windows NT. Com o KMDF e o modelo herdado do Windows NT, você pode
escrever seu driver sem se preocupar com Plug and Play (PnP) e gerenciamento de
energia. Em vez disso, você pode se concentrar nas tarefas principais do seu motorista.
Com o KMDF, você não precisa se preocupar com PnP e energia, porque a estrutura lida
com PnP e energia para você. Com o modelo herdado do Windows NT, você não
precisa se preocupar com PnP e energia porque os serviços de modo kernel operam em
um ambiente que é completamente independente do PnP e do gerenciamento de
energia.
Nossa recomendação é que você use o KMDF, especialmente se já estiver familiarizado
com ele. Se você quiser que seu driver seja completamente independente de PnP e
gerenciamento de energia, use o modelo herdado do Windows NT. Se você precisar
escrever um driver de software que esteja ciente de transições de energia ou eventos
PnP, você não pode usar o modelo herdado do Windows NT; você deve usar KMDF.
Nota: No caso muito raro em que você precisa escrever um driver de software que
esteja ciente de eventos PnP ou de energia, e seu driver precise acessar dados que não
estão disponíveis por meio do KMDF, você deve usar o WDM.
Escolhendo um modelo de driver para um
driver de sistema de arquivos
Para obter ajuda com a escolha de um modelo para um driver de sistema de arquivos,
consulte Exemplos de driver de sistema de arquivos. Observe que os drivers do sistema
de arquivos podem ser complexos e podem exigir conhecimento de conceitos
avançados para o desenvolvimento de drivers.
Escolhendo um modelo de driver para um
driver de filtro do sistema de arquivos
Para obter ajuda com a escolha de um modelo para um driver de filtro do sistema de
arquivos, consulte Drivers de minifiltro do sistema de arquivos e Drivers de filtro do
sistema de arquivos.
Escolhendo um modelo de driver para um
driver de minifiltro do sistema de arquivos
Para obter ajuda para escolher um modelo para um driver de minifiltro do sistema de
arquivos, consulte Drivers de minifiltro do sistema de arquivos.
Artigos relacionados
Estrutura de driver de modo kernel
Estrutura de driver de modo de usuário
Comentários
Esta página foi útil? Yes No
Fornecer comentários sobre o produto | Obter ajuda no Microsoft Q&A
Gravar um KMDF (Driver do Windows
Olá, Mundo)
Artigo • 16/12/2023
Este artigo descreve como escrever um pequeno driver Universal do Windows usando o
KMDF (Kernel-Mode Driver Framework) e, em seguida, implantar e instalar o driver em
um computador separado.
Antes de prosseguir, conclua as etapas de instalação listadas em Baixar o WDK (Kit de
Driver do Windows).
As Ferramentas de Depuração para Windows são incluídas quando você instala o WDK.
Criar e criar um driver
1. Abra o Microsoft Visual Studio. No menu Arquivo , escolha Novo > Projeto.
2. Na caixa de diálogo Criar um novo projeto , selecione C++ na lista suspensa à
esquerda, escolha Windows na lista suspensa intermediária e escolha Driver na
lista suspensa à direita.
3. Selecione Driver do Modo Kernel, Vazio (KMDF) na lista de tipos de projeto.
Selecione Avançar.
4. Na caixa de diálogo Configurar seu novo projeto , insira "KmdfHelloWorld" no
campo Nome do projeto.
7 Observação
Ao criar um novo driver KMDF ou UMDF, você deve selecionar um nome de
driver que tenha 32 caracteres ou menos. Esse limite de comprimento é
definido em wdfglobals.h.
5. No campo Local , insira o diretório onde você deseja criar o novo projeto.
6. Marque Colocar solução e projeto no mesmo diretório e selecione Criar.
O Visual Studio cria um projeto e uma solução. Veja-os na janela Gerenciador de
Soluções. (Se a janela Gerenciador de Soluções não estiver visível, escolha
Gerenciador de Soluções no menu Exibir.) A solução tem um projeto de driver
chamado KmdfHelloWorld.
7. Na janela Gerenciador de Soluções, selecione e segure (ou selecione à direita) a
solução KmdfHelloWorld e escolha Configuration Manager. Escolha uma
configuração e uma plataforma para o projeto de driver. Por exemplo, escolha
Depurar e x64.
8. Na janela Gerenciador de Soluções, selecione e segure novamente (ou selecione à
direita) o projeto KmdfHelloWorld, escolha Adicionar e, em seguida, selecione
Novo Item.
9. Na caixa de diálogo Adicionar Novo Item , selecione Arquivo C++. Em Nome,
insira "Driver.c".
7 Observação
A extensão de nome de arquivo é .c, não .cpp.
Selecione Adicionar. O arquivo Driver.c é adicionado em Arquivos de Origem,
conforme mostrado aqui.
Escrever seu primeiro código de driver
Agora que você criou seu projeto de Olá, Mundo vazio e adicionou o arquivo de origem
Driver.c, escreverá o código mais básico necessário para que o driver seja executado
implementando duas funções básicas de retorno de chamada de evento.
1. Em Driver.c, comece incluindo estes cabeçalhos:
C++
#include <ntddk.h>
#include <wdf.h>
Dica
Se você não puder adicionar Ntddk.h , abra Configuração –> C/C++ – Geral –
>> Diretórios de Inclusão Adicionais e adicione C:\Program Files
(x86)\Windows Kits\10\Include\<build#>\km , substituindo <build#> pelo
diretório apropriado na instalação do WDK.
O Ntddk.h contém as principais definições de kernel do Windows para todos os
drivers, enquanto o Wdf.h contém definições para drivers com base no WDF
(Windows Driver Framework).
2. Em seguida, forneça declarações para os dois retornos de chamada que você
usará:
C++
DRIVER_INITIALIZE DriverEntry;
EVT_WDF_DRIVER_DEVICE_ADD KmdfHelloWorldEvtDeviceAdd;
3. Use o seguinte código para escrever o DriverEntry:
C++
NTSTATUS
DriverEntry(
_In_ PDRIVER_OBJECT DriverObject,
_In_ PUNICODE_STRING RegistryPath
)
{
// NTSTATUS variable to record success or failure
NTSTATUS status = STATUS_SUCCESS;
// Allocate the driver configuration object
WDF_DRIVER_CONFIG config;
// Print "Hello World" for DriverEntry
KdPrintEx(( DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL,
"KmdfHelloWorld: DriverEntry\n" ));
// Initialize the driver configuration object to register the
// entry point for the EvtDeviceAdd callback,
KmdfHelloWorldEvtDeviceAdd
WDF_DRIVER_CONFIG_INIT(&config,
KmdfHelloWorldEvtDeviceAdd
);
// Finally, create the driver object
status = WdfDriverCreate(DriverObject,
RegistryPath,
WDF_NO_OBJECT_ATTRIBUTES,
&config,
WDF_NO_HANDLE
);
return status;
}
DriverEntry é o ponto de entrada para todos os drivers, como Main() é para
muitos aplicativos de modo de usuário. O trabalho do DriverEntry é inicializar
estruturas e recursos em todo o driver. Neste exemplo, você imprimiu "Olá,
Mundo" para DriverEntry, configurou o objeto driver para registrar o ponto de
entrada do retorno de chamada EvtDeviceAdd e, em seguida, criou o objeto driver
e retornou.
O objeto de driver atua como o objeto pai de todos os outros objetos de estrutura
que você pode criar em seu driver, que incluem objetos de dispositivo, filas de E/S,
temporizadores, spinlocks e muito mais. Para obter mais informações sobre
objetos de estrutura, consulte Introdução aos objetos framework.
Dica
Para DriverEntry, é altamente recomendável manter o nome como
"DriverEntry" para ajudar na análise e depuração de código.
4. Em seguida, use o seguinte código para escrever seu
KmdfHelloWorldEvtDeviceAdd:
C++
NTSTATUS
KmdfHelloWorldEvtDeviceAdd(
_In_ WDFDRIVER Driver,
_Inout_ PWDFDEVICE_INIT DeviceInit
)
{
// We're not using the driver object,
// so we need to mark it as unreferenced
UNREFERENCED_PARAMETER(Driver);
NTSTATUS status;
// Allocate the device object
WDFDEVICE hDevice;
// Print "Hello World"
KdPrintEx(( DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL,
"KmdfHelloWorld: KmdfHelloWorldEvtDeviceAdd\n" ));
// Create the device object
status = WdfDeviceCreate(&DeviceInit,
WDF_NO_OBJECT_ATTRIBUTES,
&hDevice
);
return status;
}
EvtDeviceAdd é invocado pelo sistema quando detecta que seu dispositivo chegou.
Seu trabalho é inicializar estruturas e recursos para esse dispositivo. Neste
exemplo, você simplesmente imprimiu uma mensagem "Olá, Mundo" para
EvtDeviceAdd, criou o objeto do dispositivo e retornou. Em outros drivers que você
escreve, você pode criar filas de E/S para seu hardware, configurar um espaço de
armazenamento de contexto de dispositivo para informações específicas do
dispositivo ou executar outras tarefas necessárias para preparar seu dispositivo.
Dica
Para o dispositivo adicionar retorno de chamada, observe como você o
nomeou com o nome do driver como um prefixo
(KmdfHelloWorldEvtDeviceAdd). Em geral, recomendamos nomear as funções
do driver dessa maneira para diferenciá-las das funções de outros drivers.
DriverEntry é o único que você deve nomear exatamente isso.
5. Seu Driver.c completo agora tem esta aparência:
C++
#include <ntddk.h>
#include <wdf.h>
DRIVER_INITIALIZE DriverEntry;
EVT_WDF_DRIVER_DEVICE_ADD KmdfHelloWorldEvtDeviceAdd;
NTSTATUS
DriverEntry(
_In_ PDRIVER_OBJECT DriverObject,
_In_ PUNICODE_STRING RegistryPath
)
{
// NTSTATUS variable to record success or failure
NTSTATUS status = STATUS_SUCCESS;
// Allocate the driver configuration object
WDF_DRIVER_CONFIG config;
// Print "Hello World" for DriverEntry
KdPrintEx(( DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL,
"KmdfHelloWorld: DriverEntry\n" ));
// Initialize the driver configuration object to register the
// entry point for the EvtDeviceAdd callback,
KmdfHelloWorldEvtDeviceAdd
WDF_DRIVER_CONFIG_INIT(&config,
KmdfHelloWorldEvtDeviceAdd
);
// Finally, create the driver object
status = WdfDriverCreate(DriverObject,
RegistryPath,
WDF_NO_OBJECT_ATTRIBUTES,
&config,
WDF_NO_HANDLE
);
return status;
}
NTSTATUS
KmdfHelloWorldEvtDeviceAdd(
_In_ WDFDRIVER Driver,
_Inout_ PWDFDEVICE_INIT DeviceInit
)
{
// We're not using the driver object,
// so we need to mark it as unreferenced
UNREFERENCED_PARAMETER(Driver);
NTSTATUS status;
// Allocate the device object
WDFDEVICE hDevice;
// Print "Hello World"
KdPrintEx(( DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL,
"KmdfHelloWorld: KmdfHelloWorldEvtDeviceAdd\n" ));
// Create the device object
status = WdfDeviceCreate(&DeviceInit,
WDF_NO_OBJECT_ATTRIBUTES,
&hDevice
);
return status;
}
6. Salve Driver.c.
Este exemplo ilustra um conceito fundamental de drivers: eles são uma "coleção de
retornos de chamada" que, uma vez inicializados, sentam-se e esperam que o sistema
os chame quando precisar de algo. Uma chamada do sistema pode ser um novo evento
de chegada do dispositivo, uma solicitação de E/S de um aplicativo de modo de usuário,
um evento de desligamento de energia do sistema, uma solicitação de outro driver ou
um evento de remoção surpresa quando um usuário desconecta o dispositivo
inesperadamente. Felizmente, para dizer "Olá, Mundo", você só precisava se preocupar
com a criação de driver e dispositivo.
Em seguida, você criará seu driver.
Criar o driver
1. Na janela Gerenciador de Soluções, selecione e segure (ou selecione à direita)
Solução 'KmdfHelloWorld' (1 projeto) e escolha Configuration Manager. Escolha
uma configuração e uma plataforma para o projeto de driver. Para este exercício,
escolhemos Depurar e x64.
2. Na janela Gerenciador de Soluções, selecione e segure (ou selecione à direita)
KmdfHelloWorld e escolha Propriedades. Em Rastreamento de Todas as Opções
do Wpp>, defina Executar rastreamento Wpp como Não. Selecione Aplicar e, em
seguida, OK.
3. Para criar o driver, escolha Compilar Solução no menu Compilar . O Visual Studio
mostra o progresso do build na janela Saída . (Se a janela Saída não estiver visível,
escolha Saída no menu Exibir .) Depois de verificar se a solução foi criada com
êxito, você pode fechar o Visual Studio.
4. Para ver o driver criado, em Explorador de Arquivos, vá para a pasta
KmdfHelloWorld e, em seguida, para x64\Debug\KmdfHelloWorld. A pasta inclui:
[Link] – o arquivo de driver do modo kernel
[Link] – um arquivo de informações que o Windows usa
quando você instala o driver
[Link] – um arquivo de catálogo que o instalador usa para
verificar a assinatura de teste do driver
Dica
Se você vir DriverVer set to a date in the future ao criar o driver, altere as
configurações do projeto do driver para que o Inf2Cat defina /uselocaltime . Para
fazer isso, use Propriedades de Configuração-Inf2Cat-General-Use>>> Local
Time. Agora , Tanto Stampinf quanto Inf2Cat usam a hora local.
Implantar o driver
Normalmente, quando você testa e depura um driver, o depurador e o driver são
executados em computadores separados. O computador que executa o depurador é
chamado de computador host e o computador que executa o driver é chamado de
computador de destino. O computador de destino também é chamado de computador
de teste.
Até agora, você usou o Visual Studio para criar um driver no computador host. Agora
você precisa configurar um computador de destino.
1. Siga as instruções em Provisionar um computador para implantação e teste de
driver (WDK 10).
Dica
Ao seguir as etapas para provisionar o computador de destino
automaticamente usando um cabo de rede, anote a porta e a chave. Você os
usará posteriormente na etapa de depuração. Neste exemplo, usaremos
50000 como a porta e [Link] como a chave.
Em cenários reais de depuração de driver, é recomendável usar uma chave
gerada por KDNET. Para obter mais informações sobre como usar o KDNET
para gerar uma chave aleatória, consulte o tópico Depurar Drivers –
Laboratório Passo a Passo (Modo Kernel do Sysvad).
2. No computador host, abra sua solução no Visual Studio. Você pode clicar duas
vezes no arquivo de solução, [Link], na pasta KmdfHelloWorld.
3. Na janela Gerenciador de Soluções, selecione e segure (ou clique com o botão
direito do mouse) no projeto KmdfHelloWorld e escolha Propriedades.
4. Na janela Páginas de Propriedades kmdfHelloWorld, vá para Configuração
Propriedades > Driver Instalação Implantação>, conforme mostrado aqui.
5. Verifique Remover versões anteriores do driver antes da implantação.
6. Em Nome do Dispositivo de Destino, selecione o nome do computador que você
configurou para teste e depuração. Neste exercício, usamos um computador
chamado MyTestComputer.
7. Selecione Atualização do Driver de ID de Hardware e insira a ID de hardware do
driver. Para este exercício, a ID de hardware é Root\KmdfHelloWorld. Selecione OK.
7 Observação
Neste exercício, a ID de hardware não identifica uma parte real do hardware.
Ele identifica um dispositivo imaginário que receberá um local na árvore de
dispositivos como um filho do nó raiz. Para hardware real, não selecione
Atualização do Driver de ID de Hardware; Em vez disso, selecione Instalar e
Verificar. Você verá a ID de hardware no arquivo INF (informações do driver).
Na janela Gerenciador de Soluções, vá para Arquivos de Driver
KmdfHelloWorld >e clique duas vezes em [Link]. A ID de
hardware está localizada em [[Link]$ARCH$].
C++
[[Link]$ARCH$]
%[Link]%=KmdfHelloWorld_Device, Root\KmdfHelloWorld
8. No menu Compilar , escolha Implantar Solução. O Visual Studio copia
automaticamente os arquivos necessários para instalar e executar o driver no
computador de destino. A implantação pode levar um minuto ou dois.
Quando você implanta um driver, os arquivos de driver são copiados para a pasta
%Systemdrive%\drivertest\drivers no computador de teste. Se algo der errado
durante a implantação, você poderá marcar para ver se os arquivos são copiados
para o computador de teste. Verifique se os arquivos .inf, .cat, certificado de teste e
.sys e quaisquer outros arquivos necessários estão presentes na pasta
%systemdrive%\drivertest\drivers.
Para obter mais informações sobre como implantar drivers, consulte Implantando
um driver em um computador de teste.
Instalar o driver
Com o driver Olá, Mundo implantado no computador de destino, agora você instalará o
driver. Quando você provisionou anteriormente o computador de destino com o Visual
Studio usando a opção automática , o Visual Studio configurou o computador de
destino para executar drivers assinados de teste como parte do processo de
provisionamento. Agora você só precisa instalar o driver usando a ferramenta DevCon.
1. No computador host, navegue até a pasta Ferramentas na instalação do WDK e
localize a ferramenta DevCon. Por exemplo, examine a seguinte pasta:
C:\Arquivos de Programas (x86)\Windows Kits\10\Tools\x64\[Link]
Copie a ferramenta DevCon para seu computador remoto.
2. No computador de destino, instale o driver navegando até a pasta que contém os
arquivos de driver e, em seguida, executando a ferramenta DevCon.
a. Aqui está a sintaxe geral da ferramenta devcon que você usará para instalar o
driver:
devcon install <INF file><hardware ID>
O arquivo INF necessário para instalar esse driver é [Link]. O
arquivo INF contém a ID de hardware para instalar o binário do driver
,[Link]. Lembre-se de que a ID de hardware, localizada no arquivo
INF, é Root\KmdfHelloWorld.
b. Abra uma janela do Prompt de Comando como Administrador. Navegue até a
pasta que contém o arquivo de .sys do driver criado e insira este comando:
devcon install [Link] root\kmdfhelloworld
Se você receber uma mensagem de erro sobre o desenvolvimento não ser
reconhecido, tente adicionar o caminho à ferramenta de desenvolvimento . Por
exemplo, se você copiou para uma pasta no computador de destino chamada
C:\Tools, tente usar o seguinte comando:
c:\tools\devcon install [Link] root\kmdfhelloworld
Uma caixa de diálogo será exibida indicando que o driver de teste é um driver
sem sinal. Selecione Instalar este driver de qualquer maneira para continuar.
Depurar o driver
Agora que instalou o driver KmdfHelloWorld no computador de destino, você anexará
um depurador remotamente do computador host.
1. No computador host, abra uma janela do Prompt de Comando como
Administrador. Altere para o diretório [Link]. Usaremos a x64version de
[Link] do WDK (Kit de Driver do Windows) que foi instalado como parte da
instalação do kit do Windows. Este é o caminho padrão para [Link]:
C:\Arquivos de Programas (x86)\Kits do Windows\10\Depuradores\x64
2. Inicie o WinDbg para se conectar a uma sessão de depuração de kernel no
computador de destino usando o comando a seguir. O valor da porta e da chave
deve ser o mesmo que você usou para provisionar o computador de destino.
Usaremos 50000 para a porta e [Link] para a chave, os valores que usamos
durante a etapa de implantação. O sinalizador k indica que esta é uma sessão de
depuração de kernel.
WinDbg -k net:port=50000,key=[Link]
3. No menu Depurar , escolha Interromper. O depurador no computador host
invadirá o computador de destino. Na janela Comando do Depurador , você pode
ver o prompt de comando de depuração do kernel: kd>.
4. Neste ponto, você pode experimentar o depurador inserindo comandos no
prompt kd> . Por exemplo, você pode experimentar estes comandos:
Lm
.Sympath
.Recarregar
x KmdfHelloWorld!*
5. Para permitir que o computador de destino seja executado novamente, escolha Ir
no menu Depurar ou pressione "g" e pressione "enter".
6. Para interromper a sessão de depuração, escolha Desanexar Depurador no menu
Depurar .
) Importante
Use o comando "ir" para permitir que o computador de destino seja
executado novamente antes de sair do depurador ou se o computador de
destino permanecerá sem resposta à entrada do mouse e do teclado porque
ele ainda está falando com o depurador.
Para obter um passo a passo detalhado do processo de depuração do driver, consulte
Depurar Drivers Universais – Laboratório Passo a Passo (Echo Kernel-Mode).
Para obter mais informações sobre depuração remota, consulte Depuração remota
usando WinDbg.
Artigos relacionados
Ferramentas de Depuração para Windows
Depurar Drivers Universais – Laboratório Passo a Passo (Echo Kernel-Mode)
Escrever seu primeiro driver
Comentários
Esta página foi útil? Yes No
Fornecer comentários sobre o produto | Obter ajuda no Microsoft Q&A
Escrever um driver Universal do
Windows (UMDF 2) com base em um
modelo
Artigo • 29/06/2024
Este tópico descreve como escrever um driver Universal do Windows usando o UMDF
(User-Mode Driver Framework) 2. Você começará com um modelo do Microsoft Visual
Studio e, em seguida, implantará e instalará o driver em um computador separado.
Para começar, verifique se você tem a versão mais recente do Microsoft Visual Studio e
o WDK (Kit de Driver do Windows). Para obter links de download, consulte Baixar o WDK
(Kit de Driver do Windows).
Ferramentas de depuração para Windows é incluído quando você instala o WDK.
Criar e criar um driver
7 Observação
Ao criar um novo driver KMDF ou UMDF, você deve selecionar um nome de driver
que tenha 32 caracteres ou menos. Esse limite de comprimento é definido em
wdfglobals.h.
1. Abra o Visual Studio. No menu Arquivo, escolha Novo > Projeto.
2. Na caixa de diálogo Criar um novo projeto, selecione C++ na lista suspensa
esquerda, escolha Windows na lista suspensa do meio e escolha Driver na lista
suspensa direita.
3. Selecione Driver de modo de usuário (UMDF V2) na lista de tipos de projeto.
Selecione Avançar.
4. Na caixa de diálogo Configurar seu novo projeto, digite "UmdfDriver" no campo
Nome do projeto.
7 Observação
Ao criar um novo driver KMDF ou UMDF, você deve selecionar um nome de
driver que tenha 32 caracteres ou menos. Esse limite de comprimento é
definido em wdfglobals.h.
5. No campo Local, insira o diretório onde você deseja criar o novo projeto.
6. Marque Colocar solução e projeto no mesmo diretório e selecione Criar.
O Visual Studio cria um projeto e uma solução. Veja-os na janela Gerenciador de
Soluções. (Se o A janela Gerenciador de Soluções não está visível, escolha
Gerenciador de Soluções no menu Exibir .) A solução tem um projeto de driver
chamado UmdfDriver. Para ver o código-fonte do driver, abra qualquer um dos
arquivos em Arquivos de código-fonte. Driver.c e Device.c são bons lugares para
começar.
7. Na janela Gerenciador de Soluções, selecione e segure (ou clique com o botão
direito do mouse) Solução 'UmdfDriver' (1 de 1 projeto) e escolha Gerenciador
de Configurações. Escolha uma configuração e uma plataforma para o projeto de
driver. Por exemplo, escolha Depurar e x64.
8. Na janela Gerenciador de Soluções, selecione e segure (ou clique com o botão
direito do mouse) UmdfDriver e escolha Propriedades. Navegue até
Configurações > Gerais do Driver de Propriedades > de Configuração e observe
que o padrão Plataforma de Destino é Universal.
9. Para criar seu driver, escolha Build Solution no menu Build . O Microsoft Visual
Studio exibe o progresso da compilação na janela Saída . (Se o A janela de saída
não está visível, escolha Saída no menu Exibir.)
Verifique se a saída da compilação inclui:
syntax
> Driver is 'Universal'.
Quando você tiver verificado que a solução criada com êxito, você pode fechar o
Visual Studio.
10. Para ver o driver criado, no Explorador de Arquivos, vá para a pasta UmdfDriver e,
em seguida, para x64\Debug\UmdfDriver. O diretório inclui os seguintes arquivos:
[Link] -- o arquivo de driver de modo de usuário
[Link] -- um arquivo de informações que o Windows usa quando
você instala o driver
Implantar e instalar o driver Universal do
Windows
Normalmente, quando você testa e depura um driver, o depurador e o driver são
executados em computadores separados. O computador que executa o depurador é
chamado de computador host e o computador que executa o driver é chamado de
computador de destino. O computador de destino também é chamado de computador
de teste.
Até agora, você usou o Visual Studio para criar um driver no computador host. Agora
você precisa configurar um computador de destino. Siga as instruções em Provisionar
um computador para implantação e teste de driver (WDK 10). Em seguida, você estará
pronto para implantar, instalar, carregar e depurar seu driver:
1. No computador host, abra sua solução no Visual Studio. Você pode clicar duas
vezes no arquivo de solução, [Link], na pasta UmdfDriver.
2. Na janela Gerenciador de Soluções, selecione e segure (ou clique com o botão
direito do mouse) UmdfDriver e escolha Propriedades.
3. Na janela Páginas de Propriedades do UmdfDriver, vá para Implantação de
Instalação > do Driver de Propriedades > de Configuração, conforme mostrado
aqui.
4. Marque Remover versões anteriores do driver antes da implantação.
5. Em Nome do Dispositivo de Destino, selecione o nome do computador que você
configurou para teste e depuração.
6. Selecione Atualização de driver de ID de hardware e insira a ID de hardware do
driver. Neste exercício, a ID de hardware é Root\UmdfDriver. Selecione OK.
Observação Neste exercício, a ID de hardware não identifica uma peça real de
hardware. Ele identifica um dispositivo imaginário que receberá um lugar na árvore
de dispositivos como um filho do nó raiz. Para hardware real, não selecione
Atualização de driver de ID de hardware, em vez disso, selecione Instalar e
verificar. Você pode ver a ID do hardware no arquivo de informações do driver
(INF). Na janela Gerenciador de Soluções, vá para Arquivos de Driver UmdfDriver >
e clique duas vezes em [Link]. A ID de hardware está em
[[Link]$ARCH$].
ManagedCPlusPlus
[[Link]$ARCH$]
%DeviceName%=MyDevice_Install,Root\UmdfDriver
7. No menu Depurar, escolha Iniciar Depuração ou pressione F5 no teclado.
8. Aguarde até que o driver tenha sido implantado, instalado e carregado no
computador de destino. Isso pode levar vários minutos.
Usando o DMF (Driver Module Framework)
O DMF (Driver Module Framework) é uma extensão do WDF que permite
funcionalidade extra para um desenvolvedor de driver WDF. Ele ajuda os
desenvolvedores a escrever qualquer tipo de driver WDF melhor e mais rápido.
DMF como um framework permite a criação de objetos WDF chamados DMF Modules.
O código para esses módulos DMF pode ser compartilhado entre drivers diferentes.
Além disso, o DMF agrupa uma biblioteca de módulos DMF que desenvolvemos para
nossos drivers e achamos que forneceriam valor a outros desenvolvedores de drivers.
O DMF não substitui o WDF. DMF é uma segunda estrutura que é usada com WDF. O
desenvolvedor que aproveita o DMF ainda usa o WDF e todas as suas primitivas para
gravar drivers de dispositivo.
Para obter mais informações, consulte Driver Module Framework (DMF).
Tópicos relacionados
Desenvolvimento, teste e implantação de drivers
Ferramentas de Depuração para Windows
Escreva seu primeiro driver
Comentários
Esta página foi útil? Yes No
Fornecer comentários sobre o produto | Obter ajuda no Microsoft Q&A
Gravar um KMDF (Driver do Windows
Olá, Mundo)
Artigo • 16/12/2023
Este artigo descreve como escrever um pequeno driver Universal do Windows usando o
KMDF (Kernel-Mode Driver Framework) e, em seguida, implantar e instalar o driver em
um computador separado.
Antes de prosseguir, conclua as etapas de instalação listadas em Baixar o WDK (Kit de
Driver do Windows).
As Ferramentas de Depuração para Windows são incluídas quando você instala o WDK.
Criar e criar um driver
1. Abra o Microsoft Visual Studio. No menu Arquivo , escolha Novo > Projeto.
2. Na caixa de diálogo Criar um novo projeto , selecione C++ na lista suspensa à
esquerda, escolha Windows na lista suspensa intermediária e escolha Driver na
lista suspensa à direita.
3. Selecione Driver do Modo Kernel, Vazio (KMDF) na lista de tipos de projeto.
Selecione Avançar.
4. Na caixa de diálogo Configurar seu novo projeto , insira "KmdfHelloWorld" no
campo Nome do projeto.
7 Observação
Ao criar um novo driver KMDF ou UMDF, você deve selecionar um nome de
driver que tenha 32 caracteres ou menos. Esse limite de comprimento é
definido em wdfglobals.h.
5. No campo Local , insira o diretório onde você deseja criar o novo projeto.
6. Marque Colocar solução e projeto no mesmo diretório e selecione Criar.
O Visual Studio cria um projeto e uma solução. Veja-os na janela Gerenciador de
Soluções. (Se a janela Gerenciador de Soluções não estiver visível, escolha
Gerenciador de Soluções no menu Exibir.) A solução tem um projeto de driver
chamado KmdfHelloWorld.
7. Na janela Gerenciador de Soluções, selecione e segure (ou selecione à direita) a
solução KmdfHelloWorld e escolha Configuration Manager. Escolha uma
configuração e uma plataforma para o projeto de driver. Por exemplo, escolha
Depurar e x64.
8. Na janela Gerenciador de Soluções, selecione e segure novamente (ou selecione à
direita) o projeto KmdfHelloWorld, escolha Adicionar e, em seguida, selecione
Novo Item.
9. Na caixa de diálogo Adicionar Novo Item , selecione Arquivo C++. Em Nome,
insira "Driver.c".
7 Observação
A extensão de nome de arquivo é .c, não .cpp.
Selecione Adicionar. O arquivo Driver.c é adicionado em Arquivos de Origem,
conforme mostrado aqui.
Escrever seu primeiro código de driver
Agora que você criou seu projeto de Olá, Mundo vazio e adicionou o arquivo de origem
Driver.c, escreverá o código mais básico necessário para que o driver seja executado
implementando duas funções básicas de retorno de chamada de evento.
1. Em Driver.c, comece incluindo estes cabeçalhos:
C++
#include <ntddk.h>
#include <wdf.h>
Dica
Se você não puder adicionar Ntddk.h , abra Configuração –> C/C++ – Geral –
>> Diretórios de Inclusão Adicionais e adicione C:\Program Files
(x86)\Windows Kits\10\Include\<build#>\km , substituindo <build#> pelo
diretório apropriado na instalação do WDK.
O Ntddk.h contém as principais definições de kernel do Windows para todos os
drivers, enquanto o Wdf.h contém definições para drivers com base no WDF
(Windows Driver Framework).
2. Em seguida, forneça declarações para os dois retornos de chamada que você
usará:
C++
DRIVER_INITIALIZE DriverEntry;
EVT_WDF_DRIVER_DEVICE_ADD KmdfHelloWorldEvtDeviceAdd;
3. Use o seguinte código para escrever o DriverEntry:
C++
NTSTATUS
DriverEntry(
_In_ PDRIVER_OBJECT DriverObject,
_In_ PUNICODE_STRING RegistryPath
)
{
// NTSTATUS variable to record success or failure
NTSTATUS status = STATUS_SUCCESS;
// Allocate the driver configuration object
WDF_DRIVER_CONFIG config;
// Print "Hello World" for DriverEntry
KdPrintEx(( DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL,
"KmdfHelloWorld: DriverEntry\n" ));
// Initialize the driver configuration object to register the
// entry point for the EvtDeviceAdd callback,
KmdfHelloWorldEvtDeviceAdd
WDF_DRIVER_CONFIG_INIT(&config,
KmdfHelloWorldEvtDeviceAdd
);
// Finally, create the driver object
status = WdfDriverCreate(DriverObject,
RegistryPath,
WDF_NO_OBJECT_ATTRIBUTES,
&config,
WDF_NO_HANDLE
);
return status;
}
DriverEntry é o ponto de entrada para todos os drivers, como Main() é para
muitos aplicativos de modo de usuário. O trabalho do DriverEntry é inicializar
estruturas e recursos em todo o driver. Neste exemplo, você imprimiu "Olá,
Mundo" para DriverEntry, configurou o objeto driver para registrar o ponto de
entrada do retorno de chamada EvtDeviceAdd e, em seguida, criou o objeto driver
e retornou.
O objeto de driver atua como o objeto pai de todos os outros objetos de estrutura
que você pode criar em seu driver, que incluem objetos de dispositivo, filas de E/S,
temporizadores, spinlocks e muito mais. Para obter mais informações sobre
objetos de estrutura, consulte Introdução aos objetos framework.
Dica
Para DriverEntry, é altamente recomendável manter o nome como
"DriverEntry" para ajudar na análise e depuração de código.
4. Em seguida, use o seguinte código para escrever seu
KmdfHelloWorldEvtDeviceAdd:
C++
NTSTATUS
KmdfHelloWorldEvtDeviceAdd(
_In_ WDFDRIVER Driver,
_Inout_ PWDFDEVICE_INIT DeviceInit
)
{
// We're not using the driver object,
// so we need to mark it as unreferenced
UNREFERENCED_PARAMETER(Driver);
NTSTATUS status;
// Allocate the device object
WDFDEVICE hDevice;
// Print "Hello World"
KdPrintEx(( DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL,
"KmdfHelloWorld: KmdfHelloWorldEvtDeviceAdd\n" ));
// Create the device object
status = WdfDeviceCreate(&DeviceInit,
WDF_NO_OBJECT_ATTRIBUTES,
&hDevice
);
return status;
}
EvtDeviceAdd é invocado pelo sistema quando detecta que seu dispositivo chegou.
Seu trabalho é inicializar estruturas e recursos para esse dispositivo. Neste
exemplo, você simplesmente imprimiu uma mensagem "Olá, Mundo" para
EvtDeviceAdd, criou o objeto do dispositivo e retornou. Em outros drivers que você
escreve, você pode criar filas de E/S para seu hardware, configurar um espaço de
armazenamento de contexto de dispositivo para informações específicas do
dispositivo ou executar outras tarefas necessárias para preparar seu dispositivo.
Dica
Para o dispositivo adicionar retorno de chamada, observe como você o
nomeou com o nome do driver como um prefixo
(KmdfHelloWorldEvtDeviceAdd). Em geral, recomendamos nomear as funções
do driver dessa maneira para diferenciá-las das funções de outros drivers.
DriverEntry é o único que você deve nomear exatamente isso.
5. Seu Driver.c completo agora tem esta aparência:
C++
#include <ntddk.h>
#include <wdf.h>
DRIVER_INITIALIZE DriverEntry;
EVT_WDF_DRIVER_DEVICE_ADD KmdfHelloWorldEvtDeviceAdd;
NTSTATUS
DriverEntry(
_In_ PDRIVER_OBJECT DriverObject,
_In_ PUNICODE_STRING RegistryPath
)
{
// NTSTATUS variable to record success or failure
NTSTATUS status = STATUS_SUCCESS;
// Allocate the driver configuration object
WDF_DRIVER_CONFIG config;
// Print "Hello World" for DriverEntry
KdPrintEx(( DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL,
"KmdfHelloWorld: DriverEntry\n" ));
// Initialize the driver configuration object to register the
// entry point for the EvtDeviceAdd callback,
KmdfHelloWorldEvtDeviceAdd
WDF_DRIVER_CONFIG_INIT(&config,
KmdfHelloWorldEvtDeviceAdd
);
// Finally, create the driver object
status = WdfDriverCreate(DriverObject,
RegistryPath,
WDF_NO_OBJECT_ATTRIBUTES,
&config,
WDF_NO_HANDLE
);
return status;
}
NTSTATUS
KmdfHelloWorldEvtDeviceAdd(
_In_ WDFDRIVER Driver,
_Inout_ PWDFDEVICE_INIT DeviceInit
)
{
// We're not using the driver object,
// so we need to mark it as unreferenced
UNREFERENCED_PARAMETER(Driver);
NTSTATUS status;
// Allocate the device object
WDFDEVICE hDevice;
// Print "Hello World"
KdPrintEx(( DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL,
"KmdfHelloWorld: KmdfHelloWorldEvtDeviceAdd\n" ));
// Create the device object
status = WdfDeviceCreate(&DeviceInit,
WDF_NO_OBJECT_ATTRIBUTES,
&hDevice
);
return status;
}
6. Salve Driver.c.
Este exemplo ilustra um conceito fundamental de drivers: eles são uma "coleção de
retornos de chamada" que, uma vez inicializados, sentam-se e esperam que o sistema
os chame quando precisar de algo. Uma chamada do sistema pode ser um novo evento
de chegada do dispositivo, uma solicitação de E/S de um aplicativo de modo de usuário,
um evento de desligamento de energia do sistema, uma solicitação de outro driver ou
um evento de remoção surpresa quando um usuário desconecta o dispositivo
inesperadamente. Felizmente, para dizer "Olá, Mundo", você só precisava se preocupar
com a criação de driver e dispositivo.
Em seguida, você criará seu driver.
Criar o driver
1. Na janela Gerenciador de Soluções, selecione e segure (ou selecione à direita)
Solução 'KmdfHelloWorld' (1 projeto) e escolha Configuration Manager. Escolha
uma configuração e uma plataforma para o projeto de driver. Para este exercício,
escolhemos Depurar e x64.
2. Na janela Gerenciador de Soluções, selecione e segure (ou selecione à direita)
KmdfHelloWorld e escolha Propriedades. Em Rastreamento de Todas as Opções
do Wpp>, defina Executar rastreamento Wpp como Não. Selecione Aplicar e, em
seguida, OK.
3. Para criar o driver, escolha Compilar Solução no menu Compilar . O Visual Studio
mostra o progresso do build na janela Saída . (Se a janela Saída não estiver visível,
escolha Saída no menu Exibir .) Depois de verificar se a solução foi criada com
êxito, você pode fechar o Visual Studio.
4. Para ver o driver criado, em Explorador de Arquivos, vá para a pasta
KmdfHelloWorld e, em seguida, para x64\Debug\KmdfHelloWorld. A pasta inclui:
[Link] – o arquivo de driver do modo kernel
[Link] – um arquivo de informações que o Windows usa
quando você instala o driver
[Link] – um arquivo de catálogo que o instalador usa para
verificar a assinatura de teste do driver
Dica
Se você vir DriverVer set to a date in the future ao criar o driver, altere as
configurações do projeto do driver para que o Inf2Cat defina /uselocaltime . Para
fazer isso, use Propriedades de Configuração-Inf2Cat-General-Use>>> Local
Time. Agora , Tanto Stampinf quanto Inf2Cat usam a hora local.
Implantar o driver
Normalmente, quando você testa e depura um driver, o depurador e o driver são
executados em computadores separados. O computador que executa o depurador é
chamado de computador host e o computador que executa o driver é chamado de
computador de destino. O computador de destino também é chamado de computador
de teste.
Até agora, você usou o Visual Studio para criar um driver no computador host. Agora
você precisa configurar um computador de destino.
1. Siga as instruções em Provisionar um computador para implantação e teste de
driver (WDK 10).
Dica
Ao seguir as etapas para provisionar o computador de destino
automaticamente usando um cabo de rede, anote a porta e a chave. Você os
usará posteriormente na etapa de depuração. Neste exemplo, usaremos
50000 como a porta e [Link] como a chave.
Em cenários reais de depuração de driver, é recomendável usar uma chave
gerada por KDNET. Para obter mais informações sobre como usar o KDNET
para gerar uma chave aleatória, consulte o tópico Depurar Drivers –
Laboratório Passo a Passo (Modo Kernel do Sysvad).
2. No computador host, abra sua solução no Visual Studio. Você pode clicar duas
vezes no arquivo de solução, [Link], na pasta KmdfHelloWorld.
3. Na janela Gerenciador de Soluções, selecione e segure (ou clique com o botão
direito do mouse) no projeto KmdfHelloWorld e escolha Propriedades.
4. Na janela Páginas de Propriedades kmdfHelloWorld, vá para Configuração
Propriedades > Driver Instalação Implantação>, conforme mostrado aqui.
5. Verifique Remover versões anteriores do driver antes da implantação.
6. Em Nome do Dispositivo de Destino, selecione o nome do computador que você
configurou para teste e depuração. Neste exercício, usamos um computador
chamado MyTestComputer.
7. Selecione Atualização do Driver de ID de Hardware e insira a ID de hardware do
driver. Para este exercício, a ID de hardware é Root\KmdfHelloWorld. Selecione OK.
7 Observação
Neste exercício, a ID de hardware não identifica uma parte real do hardware.
Ele identifica um dispositivo imaginário que receberá um local na árvore de
dispositivos como um filho do nó raiz. Para hardware real, não selecione
Atualização do Driver de ID de Hardware; Em vez disso, selecione Instalar e
Verificar. Você verá a ID de hardware no arquivo INF (informações do driver).
Na janela Gerenciador de Soluções, vá para Arquivos de Driver
KmdfHelloWorld >e clique duas vezes em [Link]. A ID de
hardware está localizada em [[Link]$ARCH$].
C++
[[Link]$ARCH$]
%[Link]%=KmdfHelloWorld_Device, Root\KmdfHelloWorld
8. No menu Compilar , escolha Implantar Solução. O Visual Studio copia
automaticamente os arquivos necessários para instalar e executar o driver no
computador de destino. A implantação pode levar um minuto ou dois.
Quando você implanta um driver, os arquivos de driver são copiados para a pasta
%Systemdrive%\drivertest\drivers no computador de teste. Se algo der errado
durante a implantação, você poderá marcar para ver se os arquivos são copiados
para o computador de teste. Verifique se os arquivos .inf, .cat, certificado de teste e
.sys e quaisquer outros arquivos necessários estão presentes na pasta
%systemdrive%\drivertest\drivers.
Para obter mais informações sobre como implantar drivers, consulte Implantando
um driver em um computador de teste.
Instalar o driver
Com o driver Olá, Mundo implantado no computador de destino, agora você instalará o
driver. Quando você provisionou anteriormente o computador de destino com o Visual
Studio usando a opção automática , o Visual Studio configurou o computador de
destino para executar drivers assinados de teste como parte do processo de
provisionamento. Agora você só precisa instalar o driver usando a ferramenta DevCon.
1. No computador host, navegue até a pasta Ferramentas na instalação do WDK e
localize a ferramenta DevCon. Por exemplo, examine a seguinte pasta:
C:\Arquivos de Programas (x86)\Windows Kits\10\Tools\x64\[Link]
Copie a ferramenta DevCon para seu computador remoto.
2. No computador de destino, instale o driver navegando até a pasta que contém os
arquivos de driver e, em seguida, executando a ferramenta DevCon.
a. Aqui está a sintaxe geral da ferramenta devcon que você usará para instalar o
driver:
devcon install <INF file><hardware ID>
O arquivo INF necessário para instalar esse driver é [Link]. O
arquivo INF contém a ID de hardware para instalar o binário do driver
,[Link]. Lembre-se de que a ID de hardware, localizada no arquivo
INF, é Root\KmdfHelloWorld.
b. Abra uma janela do Prompt de Comando como Administrador. Navegue até a
pasta que contém o arquivo de .sys do driver criado e insira este comando:
devcon install [Link] root\kmdfhelloworld
Se você receber uma mensagem de erro sobre o desenvolvimento não ser
reconhecido, tente adicionar o caminho à ferramenta de desenvolvimento . Por
exemplo, se você copiou para uma pasta no computador de destino chamada
C:\Tools, tente usar o seguinte comando:
c:\tools\devcon install [Link] root\kmdfhelloworld
Uma caixa de diálogo será exibida indicando que o driver de teste é um driver
sem sinal. Selecione Instalar este driver de qualquer maneira para continuar.
Depurar o driver
Agora que instalou o driver KmdfHelloWorld no computador de destino, você anexará
um depurador remotamente do computador host.
1. No computador host, abra uma janela do Prompt de Comando como
Administrador. Altere para o diretório [Link]. Usaremos a x64version de
[Link] do WDK (Kit de Driver do Windows) que foi instalado como parte da
instalação do kit do Windows. Este é o caminho padrão para [Link]:
C:\Arquivos de Programas (x86)\Kits do Windows\10\Depuradores\x64
2. Inicie o WinDbg para se conectar a uma sessão de depuração de kernel no
computador de destino usando o comando a seguir. O valor da porta e da chave
deve ser o mesmo que você usou para provisionar o computador de destino.
Usaremos 50000 para a porta e [Link] para a chave, os valores que usamos
durante a etapa de implantação. O sinalizador k indica que esta é uma sessão de
depuração de kernel.
WinDbg -k net:port=50000,key=[Link]
3. No menu Depurar , escolha Interromper. O depurador no computador host
invadirá o computador de destino. Na janela Comando do Depurador , você pode
ver o prompt de comando de depuração do kernel: kd>.
4. Neste ponto, você pode experimentar o depurador inserindo comandos no
prompt kd> . Por exemplo, você pode experimentar estes comandos:
Lm
.Sympath
.Recarregar
x KmdfHelloWorld!*
5. Para permitir que o computador de destino seja executado novamente, escolha Ir
no menu Depurar ou pressione "g" e pressione "enter".
6. Para interromper a sessão de depuração, escolha Desanexar Depurador no menu
Depurar .
) Importante
Use o comando "ir" para permitir que o computador de destino seja
executado novamente antes de sair do depurador ou se o computador de
destino permanecerá sem resposta à entrada do mouse e do teclado porque
ele ainda está falando com o depurador.
Para obter um passo a passo detalhado do processo de depuração do driver, consulte
Depurar Drivers Universais – Laboratório Passo a Passo (Echo Kernel-Mode).
Para obter mais informações sobre depuração remota, consulte Depuração remota
usando WinDbg.
Artigos relacionados
Ferramentas de Depuração para Windows
Depurar Drivers Universais – Laboratório Passo a Passo (Echo Kernel-Mode)
Escrever seu primeiro driver
Comentários
Esta página foi útil? Yes No
Fornecer comentários sobre o produto | Obter ajuda no Microsoft Q&A
Tutorial: Escrever um KMDF (driver
Universal do Windows) com base em
um modelo
Artigo • 30/12/2024
Este tópico descreve como escrever um driver universal do Windows usando o Kernel-
Mode Driver Framework (KMDF). Você começará com um modelo do Microsoft Visual
Studio e, em seguida, implantará e instalará seu driver em um computador separado.
Pré-requisitos
Siga as etapas para instalar do Windows Driver Kit (WDK). Ferramentas de
Depuração para Windows são incluídas quando você instala o WDK.
Instale Visual Studio 2022 . Ao instalar o Visual Studio 2022, selecione a carga de
trabalho Desenvolvimento para Desktop com C++ e, em Componentes
Individuais, adicione:
MSVC v143 – Bibliotecas com mitigação de Spectre do VS 2022 C++
ARM64/ARM64EC (mais recentes)
MSVC v143 – bibliotecas com mitigação de Spectre VS 2022 C++ x64/x86 (mais
recente)
ATL do C++ para as mais recentes ferramentas de build v143 com Mitigações
de Espectro (ARM64/ARM64EC)
ATL do C++ para as mais recentes ferramentas de build v143 com Mitigações
de Espectro (x86 & x64)
C++ MFC for latest v143 build tools with Spectre Mitigations
(ARM64/ARM64EC)
MFC do C++ para as mais recentes ferramentas de build v143 com Mitigações
de Espectro (x86 & x64)
Windows Driver Kit
Criar e desenvolver um driver
1. Abra o Microsoft Visual Studio. No menu Arquivo, escolha Novo > Projeto.
2. Na caixa de diálogo Criar um novo projeto, selecione C++ na lista suspensa à
esquerda, escolha Windows na lista suspensa no meio e escolha Driver na lista
suspensa à direita.
3. Selecione Kernel Mode Driver (KMDF) na lista de tipos de projeto. Selecione
Avançar.
Dica
Se você não conseguir encontrar modelos de projeto de driver no Visual
Studio, a extensão do WDK do Visual Studio não foi instalada corretamente.
Para resolver isso, execute o Instalador do Visual Studio, selecione Modificar,
adicione Kits de Driver do Windows na guia Componente Individual e
selecione Modificar.
4. Na caixa de diálogo Configurar o novo projeto, insira "KmdfDriver" no campo
Nome do projeto.
7 Observação
Ao criar um novo driver KMDF ou UMDF, você deve selecionar um nome de
driver com 32 caracteres ou menos. Esse limite de comprimento é definido
em wdfglobals.h.
5. No campo Local, insira o diretório no qual você deseja criar o novo projeto.
6. Verifique Colocar solução e projeto no mesmo diretório e selecione Criar.
O Visual Studio cria um projeto e uma solução. Você pode vê-los na janela do
Gerenciador de Soluções . (Se a janela do Gerenciador de Soluções não estiver
visível, escolha do Gerenciador de Soluções no menu Exibição.) A solução tem um
projeto de driver chamado KmdfDriver. Para ver o código-fonte do driver, abra
qualquer um dos arquivos em Arquivos de Origem. Driver.c e Device.c são bons
locais para começar.
7. Na janela Gerenciador de Soluções, selecione e segure (ou clique com o botão
direito do mouse) KmdfDriver, e escolha Propriedades. Navegue até Propriedades
de Configuração > Configurações de Driver > Geral e observe que Plataforma de
Destino usa o padrão Universal.
8. Para compilar o driver, escolha Compilar Solução no menu Compilar. O Microsoft
Visual Studio exibe o progresso da compilação na janela Saída. (Se a janela Saída
não estiver visível, escolha Saída no menu Exibir.)
Verifique se a saída de build inclui:
Saída
> Driver is 'Universal'.
Após verificar que a solução foi criada com êxito, você pode fechar o Visual Studio.
9. Para ver o driver compilado, no Explorador de Arquivos, vá para sua pasta
KmdfDriver e, em seguida, para x64\Debug\KmdfDriver. O diretório inclui os
seguintes arquivos:
[Link] -- o arquivo de driver no modo kernel
[Link] – um arquivo de informações que o Windows usa quando
você instala o driver
Implantar o driver
Normalmente, quando você testa e depura um driver, o depurador e o driver são
executados em computadores separados. O computador que executa o depurador é
chamado de computador hoste o computador que executa o driver é chamado de
computador de destino. O computador de destino também é chamado de computador de
teste. Para obter mais informações sobre drivers de depuração, consulte Ferramentas de
Depuração para Windows.
Até agora, você usou o Visual Studio para criar um driver no computador host. Agora
você precisa configurar um computador de destino.
1. Siga as instruções em Provisionar um computador para implantação e teste de
driver (WDK 10).
Dica
Ao seguir as etapas para provisionar o computador de destino
automaticamente usando um cabo de rede, anote a porta e a chave. Você os
usará posteriormente na etapa de debugging. Neste exemplo, usaremos
50000 como porta e [Link] como a chave.
Em cenários reais de depuração de driver, recomendamos usar uma chave
gerada por KDNET. Para obter mais informações sobre como usar o KDNET
para gerar uma chave aleatória, consulte o tópico Drivers de Depuração –
Laboratório Passo a Passo (Modo Kernel do Sysvad).
2. No computador host, abra sua solução no Visual Studio. Você pode clicar duas
vezes no arquivo de solução, [Link], na pasta KmdfDriver.
3. Na janela Gerenciador de Soluções, selecione e segure (ou clique com o botão
direito do mouse) no projeto KmdfDriver e escolha Propriedades.
4. Na janela Páginas de Propriedades do Pacote KmdfDriver, no painel esquerdo, vá
para Propriedades de Configuração > Instalação do Driver > Implantação.
5. Marque a caixa Remover versões anteriores do driver antes da implantação.
6. Para Nome do Computador Remoto, selecione o nome do computador que você
configurou para teste e depuração. Neste exercício, usamos um computador
chamado MyTestComputer.
7. Selecione Atualização de driver de ID de hardware e insira a ID de hardware do
driver. Neste exercício, a ID de hardware é Root\KmdfDriver. Selecione OK.
7 Observação
Neste exercício, a ID de hardware não identifica uma parte real do hardware.
Ela identifica um dispositivo imaginário que receberá um lugar na árvore de
dispositivos como filho do nó raiz. Para hardware real, não selecione a opção
Atualização do Driver de ID de Hardware; em vez disso, selecione Instalar e
Verificar. Você verá a ID de hardware no arquivo INF (informações do driver).
Na janela Gerenciador de Soluções, vá para KmdfDriver Arquivos de Driver >
e clique duas vezes em [Link]. A ID de hardware está localizada em
[[Link]$ARCH$].
C++
[[Link]$ARCH$]
%[Link]%=KmdfDriver_Device, Root\KmdfDriver
8. No menu Compilar, escolha Implantar Solução. O Visual Studio copia
automaticamente os arquivos necessários para instalar e executar o driver no
computador de destino. Isso pode levar um minuto ou dois.
Quando você implanta um driver, os arquivos de driver são copiados para a pasta
\drivertest\drivers do %Systemdrive%no computador de teste. Se algo der errado
durante a implantação, você poderá verificar se os arquivos são copiados para o
computador de teste. Verifique se os arquivos .inf, .cat, test cert e .sys e quaisquer
outros arquivos necessários estão presentes na pasta \drivertest\drivers do
%systemdrive%.
Para obter mais informações sobre como implantar drivers, consulte Implantando
um driver em um computador de teste.
Instalar o driver
Com o driver KMDF implantado no computador de destino, agora você instalará o
driver. Quando você provisionou anteriormente o computador de destino com o Visual
Studio usando a opção automática, o Visual Studio configurou o computador de destino
para executar drivers assinados de teste como parte do processo de provisionamento.
Agora você só precisa instalar o driver usando a ferramenta DevCon.
1. No computador host, navegue até a pasta Ferramentas na instalação do WDK e
localize a ferramenta DevCon. Por exemplo, examine a seguinte pasta:
C:\Program Files (x86)\Windows Kits\10\Tools\x64\[Link]
Copie a ferramenta DevCon para seu computador remoto.
2. No computador de destino, instale o driver navegando até a pasta que contém os
arquivos de driver e executando a ferramenta DevCon.
a. Aqui está a sintaxe geral da ferramenta de desenvolvimento que você usará
para instalar o driver:
instalar devcon <arquivo INF><ID de hardware>
O arquivo INF necessário para instalar esse driver é [Link]. O arquivo
INF contém a ID de hardware para instalar o binário do driver, [Link].
Lembre-se de que a ID de hardware, localizada no arquivo INF, é
Root\KmdfDriver.
b. Abra uma janela do Prompt de Comando como Administrador. Navegue até a
pasta do pacote do driver e, em seguida, insira este comando:
instalar devcon [Link] root\kmdfdriver
Se você obtiver uma mensagem de erro sobre devcon não reconhecida, tente
adicionar o caminho para a ferramenta devcon. Por exemplo, se você copiá-la
para uma pasta no computador de destino chamada C:\Tools, tente usar o
seguinte comando:
c:\tools\devcon install [Link] root\kmdfdriver
Uma caixa de diálogo aparecerá indicando que o driver de teste é um driver
não assinado. Selecione Instalar esse driver de qualquer maneira continuar.
Depurar o driver
Agora que instalou o driver KMDF no computador de destino, você conectará um
depurador remotamente do computador host.
1. No computador host, abra uma janela do Prompt de Comando como
Administrador. Mude para o diretório [Link]. Usaremos a versão x64 do
[Link] do Windows Driver Kit (WDK) que foi instalada como parte da
instalação do kit do Windows. Este é o caminho padrão para [Link]:
C:\Arquivos de Programas (x86)\Windows Kits\10\Depuradores\x64
2. Inicie o WinDbg para se conectar a uma sessão de depuração de kernel no
computador de destino usando o comando a seguir. O valor da porta e da chave
deve ser o mesmo que você usou para provisionar o computador de destino.
Usaremos 50000 para a porta e [Link] para a chave, os valores que usamos
durante a etapa de implantação. O sinalizador k indica que esta é uma sessão de
depuração de kernel.
WinDbg -k net:port=50000,key=[Link]
3. No menu Depurar, escolha Interromper. O depurador no computador host
invadirá o computador de destino. Na janela Comando do Depurador, você pode
ver o prompt de comando de depuração do kernel: kd>.
4. Neste ponto, você pode experimentar o depurador inserindo comandos no
prompt kd>. Por exemplo, você pode experimentar estes comandos:
lm
.sympath
.reload
x KmdfDriver!*
5. Para permitir que o computador de destino seja executado novamente, escolha Ir
no menu Depurar ou pressione "g" e "enter".
6. Para interromper a sessão de depuração, escolha Desanexar Debuggee do menu
Depurar.
) Importante
Certifique-se de usar o comando "go" para permitir que o computador de
destino volte a funcionar antes de sair do depurador, ou o computador de
destino permanecerá sem resposta à entrada do mouse e teclado, pois ainda
estará se comunicando com o depurador.
Para obter um passo a passo detalhado do processo de depuração do driver, consulte
Depuração de Drivers Universais - Laboratório Passo a Passo (Echo Kernel-Mode).
Para obter mais informações sobre depuração remota, consulte Depuração Remota
usando o WinDbg.
Usando o DMF (Driver Module Framework)
O DMF (Driver Module Framework) é uma extensão do WDF que permite funcionalidade
extra para um desenvolvedor de driver do WDF. Ele ajuda os desenvolvedores a escrever
qualquer tipo de driver WDF melhor e mais rápido.
O DMF como uma estrutura permite a criação de objetos WDF chamados Módulos
DMF. O código desses módulos DMF pode ser compartilhado entre drivers diferentes.
Além disso, o DMF agrupa uma biblioteca de módulos DMF que desenvolvemos para
nossos drivers e achamos que forneceria valor para outros desenvolvedores de driver.
O DMF não substitui o WDF. O DMF é uma segunda estrutura usada com o WDF. O
desenvolvedor que aproveita o DMF ainda usa o WDF e todos os seus primitivos para
gravar drivers de dispositivo.
Para obter mais informações, consulte DMF (Driver Module Framework) .
Tópicos relacionados
Desenvolvimento, teste e implantação de drivers
Ferramentas de Depuração para Windows
Depurar drivers universais ― Laboratório passo a passo (Echo Kernel-Mode)
Escreva seu primeiro driver
Comentários
Esta página foi útil? Yes No
Fornecer comentários sobre o produto | Obter ajuda no Microsoft Q&A
Do código de exemplo ao driver de
produção. O que mudar nos exemplos
Artigo • 04/10/2024
Este tópico descreve alterações importantes que precisam ser feitas nos drivers de
exemplo do WDK antes de liberar drivers de dispositivo com base no código de
exemplo.
Além das alterações descritas aqui, todos os drivers devem usar as práticas
recomendadas descritas em Criar drivers confiáveis no modo kernel e em Práticas
recomendadas de desenvolvimento de driver de equipe do Surface. Todos os drivers
também devem seguir as diretrizes fornecidas nas Diretrizes de Segurança do Driver.
Exemplos de drivers do WDK: identificadores
exclusivos
O Kit de driver do Windows (WDK) contém uma grande variedade de drivers de
exemplo que demonstram técnicas úteis para o desenvolvimento de drivers. Você pode
usar esses exemplos como base para seus próprios drivers, mas antes de liberar o driver,
você deve alterar determinados aspectos específicos do dispositivo do exemplo, além
do código operacional óbvio, para aplicar exclusivamente ao seu próprio dispositivo e
driver. Os escritores de driver às vezes ignoram esses detalhes.
Os itens exatos que você deve alterar variam de um exemplo para outro, mas, em geral,
eles identificam um dispositivo, interface ou driver específico. Por exemplo, se o driver
de exemplo contiver qualquer um dos seguintes itens, você deverá alterá-los para se
aplicarem ao driver e ao dispositivo:
Identificadores global exclusivos (GUIDs)
Nomes de link simbólicos
Nome do objeto do dispositivo
Marcas do pool
Definições de código de controle de E/S (IOCTL)
Nomes de qualquer arquivo copiado para a pasta do sistema
ID do dispositivo Plug and Play, ID de hardware e IDs compatíveis
Nome do serviço de driver
Descrição do dispositivo
Arquivo de recurso
Esquecer de fazer essas alterações pode resultar em falha na instalação, conflitos com
outros dispositivos e drivers no sistema e dificuldades na depuração, além de outros
erros.
Por exemplo, se você receber um erro como
...\toastDrv\kmdf\toastmon\[Link](18-18): error 1284: Class "Sample" is
reserved for use by Microsoft. isso indica que o nome "Exemplo" deve ser alterado
para um nome exclusivo para seu driver de exemplo.
GUIDs
Os drivers usam GUIDs para identificar classes de configuração de dispositivos, classes
de interface de dispositivos, eventos PnP personalizados, eventos WMI (Instrumentação
de Gerenciamento do Windows) personalizados e provedores de rastreamento do
Windows PreProcessor (WPP). Alguns GUIDs são definidos pela Microsoft e outros são
definidos por fornecedores de dispositivos e drivers.
Os GUIDs de classe de instalação do dispositivo, os GUIDs de classe de interface do
dispositivo e os GUIDs WMI para dispositivos comuns e dados WMI são definidos no
WDK ou em arquivos de cabeçalho públicos para uso por qualquer driver. Você não
deve alterar esses GUIDs.
Por exemplo, se estiver implementando um mouse, você continuará a usar
GUID_DEVINTERFACE_MOUSE, que é definido no arquivo de cabeçalho Ntddmou.h do
WDK, como a classe de interface do dispositivo. No entanto, se você definir uma nova
classe de configuração de dispositivo, deverá gerar um novo GUID de classe de
configuração de dispositivo e um nome de classe de configuração e, possivelmente,
também um novo GUID de classe de interface de dispositivo. O GUID da classe de
instalação e o GUID da classe de interface do dispositivo devem ser valores exclusivos,
eles não podem compartilhar um GUID.
Na maioria dos drivers baseados em exemplos, você deve alterar apenas os GUIDs
definidos no cabeçalho local ou no arquivo de origem de um exemplo e que, portanto,
são específicos do exemplo. Esses GUIDs podem incluir o seguinte:
Eventos PnP personalizados
Eventos WMI personalizados
Classes de interface de dispositivo para dispositivos novos ou personalizados
Provedores de rastreamento do WPP
O uso de um GUID que foi definido para outro driver pode causar conflitos se ambos os
drivers forem carregados no mesmo sistema. Por exemplo, se dois drivers diferentes
usarem o mesmo GUID para registrar uma interface de dispositivo, os clientes que
tentarem abrir a interface do dispositivo poderão abrir inadvertidamente o dispositivo
errado.
O trecho a seguir é do arquivo Driver.h incluído em todos os exemplos de driver Toaster.
Ele define o GUID da interface do dispositivo para dispositivos Toaster:
DEFINE_GUID(GUID_TOASTER_INTERFACE_STANDARD, \
0xe0b27630, 0x5434, 0x11d3, 0xb8, 0x90, 0x0, 0xc0, \
0x4f, 0xad, 0x51, 0x71);
// {E0B27630-5434-11d3-B890-00C04FAD5171}
Se você usar esse arquivo em seu próprio driver, substitua o GUID de exemplo
(mostrado acima como texto em negrito) pelo GUID da interface para seu próprio
dispositivo. Para criar um GUID, use a ferramenta Criar GUID no Microsoft Visual Studio
ou [Link], ambas incluídas no SDK (Kit de Desenvolvimento de Software) do
Microsoft Windows. Em seguida, você pode associar o GUID a uma constante simbólica
no arquivo de cabeçalho do driver, como mostra o exemplo.
Você também pode ser solicitado a criar novos GUIDs para os eventos WMI do driver.
Os exemplos de driver Toaster definem o seguinte GUID para notificação de chegada do
dispositivo de resistência:
DEFINE_GUID (TOASTER_NOTIFY_DEVICE_ARRIVAL_EVENT, \
0x1cdaff1, 0xc901, 0x45b4, 0xb3, 0x59, 0xb5, 0x54, \
0x27, 0x25, 0xe2, 0x9c);
// {01CDAFF1-C901-45b4-B359-B5542725E29C}
Você deve criar um novo GUID para cada evento WMI em seu driver.
Se o driver de exemplo usar o rastreamento de software WPP, gere um novo GUID do
provedor de rastreamento para todos os drivers que você basear no exemplo. Por
exemplo, o arquivo de cabeçalho Trace.h do exemplo Osrusbfx2 em
%WinDDK%\Src\Kmdf\Osrusbfx2\Final define um GUID de controle da seguinte
maneira:
#define WPP_CONTROL_GUIDS \
WPP_DEFINE_CONTROL_GUID( \
OsrUsbFxTraceGuid,(d23a0c5a,d307,4f0e,ae8e,E2A355AD5DAB), \
WPP_DEFINE_BIT(DBG_INIT) /* bit 0 = 0x00000001 */ \
WPP_DEFINE_BIT(DBG_PNP) /* bit 1 = 0x00000002 */ \
WPP_DEFINE_BIT(DBG_POWER) /* bit 2 = 0x00000004 */ \
WPP_DEFINE_BIT(DBG_WMI) /* bit 3 = 0x00000008 */ \
WPP_DEFINE_BIT(DBG_CREATE_CLOSE) /* bit 4 = 0x00000010 */ \
WPP_DEFINE_BIT(DBG_IOCTL) /* bit 5 = 0x00000020 */ \
WPP_DEFINE_BIT(DBG_WRITE) /* bit 6 = 0x00000040 */ \
WPP_DEFINE_BIT(DBG_READ) /* bit 7 = 0x00000080 */ \
)
Em seu próprio driver, você substituiria o texto em negrito por um nome específico do
driver e o GUID que você criou.
Nomes de link simbólicos
Se o exemplo definir um nome de link simbólico, substitua o nome no exemplo por um
nome que se aplique ao seu próprio driver. No entanto, não altere nomes de link
conhecidos, como \DosDevices\COM1. Em geral, se o nome do link for muito
semelhante ao nome do exemplo (como \DosDevices\CancelSamp), você deverá alterá-
lo.
Usar o mesmo link simbólico de outro driver tem o mesmo efeito que usar o GUID
errado da interface de dispositivo, pois as interfaces de dispositivo são essencialmente
links simbólicos.
O driver KMDF Toaster Filter em %WinDDK\Src\Kmdf\Toaster\Filter cria um nome de link
simbólico que usa uma cadeia de caracteres definida da seguinte maneira no arquivo de
cabeçalho Filter.h:
#define SYMBOLIC_NAME_STRING L"\\DosDevices\\ToasterFilter"
Altere a cadeia de caracteres em negrito para descrever com mais precisão seu próprio
driver.
Nome do objeto do dispositivo
Se o exemplo criar um nome para o objeto de dispositivo, você deverá alterar o nome
ao adaptar o código de exemplo.
O driver KMDF Toaster Filter nomeia seu objeto de dispositivo no arquivo de cabeçalho
Filter.h da seguinte maneira:
#define NTDEVICE_NAME_STRING L\\Device\\ToasterFilter
Assim como acontece com o nome do link simbólico, você deve alterar a cadeia de
caracteres para descrever seu driver.
Lembre-se de que os objetos de dispositivo nomeados podem representar um risco de
segurança. Os PDOs (objetos de dispositivo físico) devem ter nomes e a maioria desses
nomes é gerada pelo sistema em vez de atribuída explicitamente por um driver. Outros
objetos de dispositivo devem ser nomeados somente se representarem objetos de
dispositivo de controle, que são usados para comunicação de banda lateral entre um
aplicativo e um driver. A estrutura de driver de modo kernel (KMDF) e o WDM (Windows
Driver Model) habilitam que você permita que o Windows gere o nome. Essa
abordagem garante que o nome do objeto do dispositivo seja exclusivo e que usuários
sem privilégios não possam acessá-lo. Para obter detalhes, consulte Controlar o acesso
ao namespace do dispositivo e Controlar o acesso ao dispositivo em drivers KMDF.
Marcas do pool
Uma marca de pool é um literal de um a quatro caracteres que identifica uma alocação
de memória específica e pode ajudar na depuração.
Muitos dos drivers de exemplo definem uma marca de pool no arquivo de cabeçalho do
driver, como na seguinte linha de Toaster.h:
#define TOASTER_POOL_TAG (ULONG) 'saoT'
O driver define a marca de trás para frente porque o depurador a exibe na ordem
inversa. Assim, essa marca aparece como Toas na saída do depurador. Em vez de usar a
marca que o exemplo define, altere a cadeia de caracteres para identificar
exclusivamente seu próprio código.
O arquivo [Link] lista as marcas de pool usadas por componentes e drivers do
modo kernel fornecidos com o Windows. [Link] é instalado com o WDK em
%winddk%\Tools\Other<i>platform\Poolmon, onde platform é amd64, i386, ou ia64.
Não use nenhuma das marcações que aparecem nesta lista.
Definições de IOCTL
Altere todos os códigos de controle de E/S definidos por exemplo para usar um nome,
tipo de dispositivo, código de função, tipo de transferência e tipo de acesso apropriados
para seu dispositivo e driver.
Por exemplo, o exemplo Osrusbfx2 inclui a seguinte definição para
IOCTL_OSRUSBFX2_READ_SWITCHES:
#define IOCTL_OSRUSBFX2_READ_SWITCHES
CTL_CODE(FILE_DEVICE_OSRUSBFX2, \
IOCTL_INDEX + 6, \
METHOD_BUFFERED, \
FILE_READ_ACCESS)
Um driver baseado em exemplo para um dispositivo diferente exigiria modificações
nessa definição.
Nomes de arquivos
No INF ou INX, altere os nomes do driver, do coinstalador fornecido pelo fornecedor e
de quaisquer outros arquivos que o procedimento de instalação copie para a pasta do
sistema. Esses nomes de arquivo normalmente aparecem nas seções [SourceDisksFiles]
e [ClassInstall32] do INF e nas entradas CopyFiles.
O exemplo a seguir é do arquivo INX para o exemplo KMDF Featured Toaster, que está
disponível em %WinDDK%\src\kmdf\Toaster\Func\Featured. Os nomes dos arquivos
que devem ser alterados são mostrados em negrito:
[ClassInstall32]
Addreg=ToasterClassReg
CopyFiles=ToasterClassInstallerCopyFileshighlight
[ToasterClassReg]
...
HKR,,Installer32,,"[Link],ToasterClassInstaller"
...
[ToasterClassInstallerCopyFiles]
[Link]
...
Para adaptar essa parte do arquivo para um driver diferente, você alteraria "[Link]"
para o nome do arquivo do instalador da classe e alteraria a cadeia de caracteres
"ToasterClassInstaller" para descrever seu próprio instalador. Essas alterações garantem
que o procedimento de instalação copie o arquivo de coinstalador correto e que a
chave do Registro registre o nome de arquivo correto.
Não altere o nome dos coinstaladores fornecidos no WDK ou com o Windows, como os
coinstaladores KMDF, UMDF e WinUSB.
Alterações adicionais são necessárias posteriormente na seção Instalação do dispositivo
do arquivo, conforme mostrado neste exemplo:
[Toaster_Device.NT]
CopyFiles=Toaster_Device.[Link]
[Toaster_Device.[Link]]
[Link]
Neste exemplo, você alteraria o nome do arquivo em negrito para o nome do arquivo
de driver gerado.
Quando a Instalação copia os arquivos de catálogo de driver e INF, ela os renomeia,
portanto, você não precisa alterar seus nomes no pacote de driver. No entanto,
geralmente é uma boa ideia garantir que os nomes de arquivo INF e de catálogo sejam
semelhantes ao nome do arquivo de driver.
ID do dispositivo PnP, ID de hardware e IDs
compatíveis
A instalação usa a ID do dispositivo junto com IDs de hardware e IDs compatíveis para
selecionar o INF a ser usado para a instalação do dispositivo.
A ID do dispositivo é uma cadeia de caracteres definida pelo fornecedor que identifica
exclusivamente um dispositivo específico. Cada dispositivo tem exatamente uma ID de
dispositivo. O driver de barramento relata a ID do dispositivo durante a enumeração e a
Instalação a usa para corresponder o dispositivo ao arquivo INF correto. A ID do
dispositivo é definida na seção [Fabricante] do INF.
O exemplo a seguir mostra a ID do dispositivo OSR USB Fx2, conforme especificado no
arquivo [Link]:
[Manufacturer]
%MfgName%=Microsoft,NT$ARCH$
; For Win2K
[Microsoft]
%USB\VID_045E&PID_930A.DeviceDesc%=[Link],
USB\VID_0547&PID_1002
...
; For XP and later
[[Link]$ARCH$]
%USB\VID_045E&PID_930A.DeviceDesc%=[Link],
USB\VID_0547&PID_1002
Para adaptar essa diretiva INF para seu próprio driver, substitua a ID do dispositivo
mostrada em negrito pela ID do dispositivo para seu próprio dispositivo. Você também
deve alterar o nome do fabricante para o nome da sua empresa.
A ID de hardware e a ID compatível são IDs menos específicas que a Instalação usa se
não puder corresponder a ID do dispositivo a um INF. Se o INF puder dar suporte a
outros dispositivos, você deverá alterar esses valores além da ID do dispositivo. O
exemplo a seguir do driver KMDF Featured Toaster mostra uma ID de hardware:
[Manufacturer]
%StdMfg%=Standard,NT$ARCH$
; For Win2K
[Standard]
; DisplayName Section DeviceId
; ----------- ------- --------
%[Link]%=Toaster_Device,
{b85b7c50-6a01-11d2-b841-00c04fad5171}\MsToaster
; For XP and later
[[Link]$ARCH$]
%[Link]%=Toaster_Device,
{b85b7c50-6a01-11d2-b841-00c04fad5171}\MsToaster
Para adaptar essa diretiva INF para seu próprio driver, substitua a ID de hardware pela
ID do dispositivo do driver e altere "MsToaster" para uma cadeia de caracteres mais
descritiva.
Nome do serviço de driver
Atualize o nome do serviço na diretiva AddService no INF para um valor apropriado
para o driver. Se o nome do serviço de driver entrar em conflito com o de outro driver
no sistema, o driver não será instalado ou carregado.
O driver KMDF Featured Toaster nomeia seu serviço da seguinte maneira:
[Toaster_Device.[Link]]
AddService = wdffeatured, %SPSVCINST_ASSOCSERVICE%,
wdffeatured_Service_Inst
O nome do serviço é a primeira entrada na diretiva AddService. Para adaptar o INF do
Featured Toaster, você deve alterar a cadeia de caracteres em negrito para uma cadeia
de caracteres mais adequada ao seu driver. No exemplo, a entrada
wdffeatured_Service_Inst apenas faz referência a uma seção definida por INF, portanto,
alterá-la não é essencial.
Descrição do dispositivo
A descrição do dispositivo consiste em várias cadeias de caracteres que normalmente
são definidas na seção [Cadeias de Caracteres] do INF e são usadas em vários locais em
todo o INF. Por exemplo, o exemplo KMDF Featured Toaster define as seguintes cadeias
de caracteres no arquivo [Link]:
[Strings]
SPSVCINST_ASSOCSERVICE = 0x00000002
MSFT = "Microsoft"
StdMfg = "(Standard system devices)"
ClassName = "Toaster"
DiskId1 = "Toaster Device Installation Disk #1"
[Link] = "Microsoft WDF Featured Toaster"
[Link] = "Microsoft WDF Toaster Featured Device Driver"
Para modificar esse arquivo para instalar seu próprio driver, você deve alterar as cadeias
de caracteres em negrito para refletir informações sobre sua empresa, dispositivo e
driver.
Se o nome da empresa também aparecer em uma seção [Fabricante] no INF, você
também deverá alterar o nome nessa seção.
Arquivo de recurso
Drivers e outros componentes, como coinstaladores específicos de exemplo, também
têm arquivos de recurso (.rc), que definem cadeias de caracteres específicas do driver,
incluindo o nome do produto, a versão do arquivo e o nome da empresa. Altere essas
cadeias de caracteres para valores apropriados para o pacote de driver.
Resumo: o que você deve fazer?
Antes de liberar um driver baseado em um exemplo do WDK, substitua todas as
informações específicas do exemplo nos arquivos de origem, no INF e em quaisquer
outros recursos usados para criar seu próprio driver. As alterações necessárias variam de
um exemplo para outro, mas geralmente incluem qualquer informação que identifique
exclusivamente o driver de exemplo ou seu dispositivo. Os itens seguintes são típicos
das alterações que você deve fazer:
Gere e use GUIDs específicos para o driver, quando apropriado.
Atualizar o nome do link simbólico.
Atualize o nome do objeto do dispositivo ou use um nome gerado
automaticamente.
Use marcas de pool que identifiquem seu driver e não entrem em conflito com
nenhuma marca conhecida.
Defina códigos IOCTL apropriados para seu driver e dispositivo.
Atualize os nomes de todos os arquivos copiados para a pasta do sistema.
Insira a ID de dispositivo Plug and Play correta, as IDs de hardware e as IDs
compatíveis no INF.
Atualize o nome do serviço do driver no INF.
Altere a descrição do dispositivo.
Modifique todas as cadeias de caracteres específicas do driver no arquivo de
recurso.
Aderir às práticas recomendadas de segurança e confiabilidade
Informações Adicionais
Manuais
Desenvolver drivers com o Windows Driver Foundation escrito por Penny Orwick e Guy
Smith.
Tópicos WDK
Definir e exportar novos GUIDs
Controlar o acesso ao dispositivo em drivers KMDF
Desenvolvimento, teste e implantação de drivers
Criar drivers confiáveis no modo kernel
Práticas recomendadas de desenvolvimento de drivers do Surface Team
Diretrizes de segurança do driver
Escreva seu primeiro driver
Comentários
Esta página foi útil? Yes No
Fornecer comentários sobre o produto | Obter ajuda no Microsoft Q&A
Provisionar um computador para
implantação e teste de driver (WDK 10)
Artigo • 27/09/2024
O provisionamento de um computador de destino ou de teste é o processo de
configuração de um computador para implantação, teste e depuração automática de
drivers. Para provisionar um computador, use o Microsoft Visual Studio.
Um ambiente de teste e depuração tem dois computadores: o computador host e o
computador de destino. O computador de destino também é chamado de computador
de teste. Você desenvolve e cria seu driver no Visual Studio no computador host. O
depurador é executado no computador host e está disponível na interface do usuário
do Visual Studio. Quando você testa e depura um driver, o driver é executado no
computador de destino.
Certifique-se de que os computadores host e de destino possam executar ping um no
outro pelo nome. Esse processo será mais simples se ambos os computadores
pertencerem ao mesmo grupo de trabalho ou domínio de rede. Se os computadores
estiverem em um grupo de trabalho, conecte-os a um roteador em vez de um hub ou
switch.
Ao provisionar sistemas para implantação de driver, o host e os computadores de
destino devem ter a mesma versão do sistema operacional Windows.
Dica
Para obter suporte da comunidade no WDK, consulte o Fórum de Desempenho de
Hardware do Windows em Perguntas e Respostas da Microsoft.
Preparar o computador de destino para
provisionamento
1. No computador de destino, instale o sistema operacional que você usará para
executar e testar o driver.
2. Instalar a WDK. Você só precisa instalar o Visual Studio se você planeja fazer o
desenvolvimento de driver no computador de destino.
3. Se a Inicialização Segura estiver habilitada no computador de destino, desabilite-a.
Para obter informações sobre UEFI (Unified Extensible Firmware Interface) e
Inicialização Segura, consulte Firmware da UEFI.
4. Se o computador de destino for uma VM, ele deverá ser iniciado no modo não
avançado, para desabilitar a configuração do modo avançado da VM, consulte
Compartilhar dispositivos com sua máquina virtual
5. Se você estiver implantando um driver de teste na máquina de destino, habilite a
assinatura de teste de um comando elevado com bcdedit /set testsigning on
6. Se você for testar o driver com WDTF, certifique-se de habilitar o Verificador de
Driver usando a página de propriedades e reinicie a máquina de destino após a
implantação
No computador host, no Visual Studio, clique com o botão direito do mouse
no projeto de driver vá para Propriedades > Propriedades e Configuração >
Instalação do Drivere > Verificação do Driver > Habilitar Verificação de
Driver
7. No computador de destino, execute o MSI de Configuração de Destino de Teste do
WDK que corresponde à plataforma do computador de destino. Você pode
encontrar o MSI no diretório de instalação do Kit de Driver do Windows (WDK) em
Remoto.
Exemplo: C:\Arquivos de Programas (x86)\Windows Kits\10\Remote\x64\WDK Test
Target Setup x64-x64_en-[Link]
8. Se o computador de destino estiver executando o Windows Server, localize a pasta
DriverTest que acabou de ser criada pelo MSI da Instalação de Destino de Teste do
WDK. (Exemplo: c:\DriverTest). Selecione e segure (ou selecione com o botão
direito do mouse) a pasta DriverTest e escolha Propriedades. Na guia Segurança,
dê a permissão Modificar ao grupo Usuários Autenticados.
Verifique se os computadores host e de destino podem executar ping um no outro.
Abra uma janela do prompt de comando e digite ping ComputerName.
Se os computadores host e de destino estiverem associados a um grupo de trabalho e
estiverem em sub-redes diferentes, talvez seja necessário ajustar algumas configurações
de firewall para que os computadores host e de destino possam se comunicar. Siga
estas etapas:
1. No computador de destino, no Painel de Controle, vá para Rede e Internet >
Central de Compartilhamento de Rede. Observe sua rede ativa. Será Rede
pública, Rede privada ou Domínio.
2. No computador de destino, no Painel de Controle, vá para Sistema e Segurança >
Firewall do Windows > Configurações avançadas > Regras de entrada.
3. Na lista de regras de entrada, localize todas as regras de Descoberta de Rede para
sua rede ativa. (Por exemplo, localize todas as regras de Descoberta de Rede que
tenham um Perfil Privado.) Clique duas vezes em cada regra e abra a guia Escopo.
Em Endereço IP remoto, selecione Qualquer endereço IP.
4. Na lista de regras de entrada, localize todas as regras de Compartilhamento de
Arquivos e Impressoras para sua rede ativa. Para cada uma dessas regras, clique
duas vezes na regra e abra a guia Escopo . Em Endereço IP remoto, selecione
Qualquer endereço IP.
Provisionar o computador de destino
Agora você está pronto para provisionar o computador de destino do computador host
no Visual Studio.
1. No computador host, no Visual Studio, selecione o menu Extensões, aponte para
Driver, aponte para Testar e selecione Configurar Dispositivos.
2. No diálogo Configurar dispositivos, selecione Adicionar novo dispositivo.
3. Em Nome, digite o nome ou o endereço IP local do computador de destino.
Selecione Provisionar dispositivo e escolher as configurações do depurador.
4. Selecione Avançar.
5. Selecione um tipo de conexão de depuração e insira os parâmetros necessários.
Para obter mais informações sobre como configurar a depuração em vários tipos
de conexões, consulte Configuração manual da depuração do kernel de rede
KDNET e a documentação relacionada para as Ferramentas de Depuração para
Windows.
6. O processo de provisionamento leva vários minutos e pode reiniciar
automaticamente o computador de destino uma ou duas vezes. Quando o
provisionamento for concluído, selecione Concluir.
7. Reinicie o computador.
Confira também
Implantação de um driver em um computador de teste
Quando você provisiona um computador (WDK 8.1)
Comentários
Esta página foi útil? Yes No
Fornecer comentários sobre o produto | Obter ajuda no Microsoft Q&A
Introdução a drivers no Windows
Artigo • 30/12/2024
Bem-vindo à documentação do Windows Driver! Nesta seção, você aprenderá os
conceitos básicos sobre drivers, os diferentes tipos de drivers e como escrever um
driver.
7 Observação
Para entender os conceitos nesta seção, você já deve estar familiarizado com a
linguagem de programação Ce deve entender as ideias de ponteiros de função,
funções de retorno de chamada e manipuladores de eventos.
Nesta seção
O que é um driver?
Drivers internos
Escolher um modelo de driver
Escreva seu primeiro driver
Do código de exemplo ao driver de produção
Provisionar um computador para implantação e teste de driver (WDK 10)
Conceitos para todos os desenvolvedores de drivers
Tópicos relacionados
Kit de Driver do Windows (WDK)
Diretrizes de segurança do driver
Comentários
Esta página foi útil? Yes No
Fornecer comentários sobre o produto | Obter ajuda no Microsoft Q&A
Modo de usuário e modo kernel
Artigo • 27/09/2024
Um processador em um computador que executa o Windows opera em dois modos
diferentes: modo de usuário e modo kernel. O processador alterna entre esses modos
dependendo do tipo de código em execução. Os aplicativos operam no modo de
usuário, enquanto os componentes principais do sistema operacional funcionam no
modo kernel. Embora muitos drivers operem no modo kernel, alguns podem funcionar
no modo de usuário.
Modo de usuário
Quando você inicia um aplicativo no modo de usuário, o Windows cria um processo para
ele. Esse processo fornece ao aplicativo um espaço de endereço virtual privado e uma
tabela de identificador privado. Como o espaço de endereço virtual de cada aplicativo é
privado, um aplicativo não pode modificar os dados de outro aplicativo. Cada aplicativo
é executado isoladamente, garantindo que, se um falhar, ele não afete outros aplicativos
ou o sistema operacional.
O espaço de endereço virtual de um aplicativo de modo de usuário também é limitado.
Um processo em execução no modo de usuário não pode acessar endereços virtuais
reservados para o sistema operacional. Limitar o espaço de endereço virtual de um
aplicativo de modo de usuário impede que o aplicativo modifique ou prejudique dados
críticos do sistema operacional.
Modo Kernel
Todo o código em execução no modo kernel compartilha um único espaço de endereço
virtual. Como resultado, um driver no modo kernel não é isolado de outros drivers ou
do sistema operacional. Se um driver no modo kernel gravar erroneamente no endereço
virtual errado, ele poderá comprometer os dados pertencentes ao sistema operacional
ou a outro driver. Se um driver no modo kernel falhar, ele fará com que todo o sistema
operacional falhe.
O diagrama a seguir ilustra a comunicação entre os componentes do modo de usuário e
do modo kernel.
Artigos relacionados
Espaços de endereço virtual
Comentários
Esta página foi útil? Yes No
Fornecer comentários sobre o produto | Obter ajuda no Microsoft Q&A
Espaços de endereço virtuais
Artigo • 28/06/2024
Os processadores usam endereços virtuais ao ler ou gravar em locais de memória.
Durante essas operações, o processador converte o endereço virtual em um físico.
Há vários benefícios para acessar a memória usando endereços virtuais:
Um programa pode usar um intervalo contíguo de endereços virtuais para acessar
um buffer de memória grande e não contíguo na memória física.
Um programa pode usar um intervalo de endereços virtuais para acessar um buffer
de memória maior que a memória física disponível. Quando a memória física está
baixa, o gerenciador de memória salva páginas de memória física (normalmente 4
quilobytes de tamanho) em um arquivo de disco. O sistema move páginas de
dados ou código entre a memória física e o disco, conforme necessário.
Os endereços virtuais usados por processos diferentes são isolados. O código em
um processo não pode alterar a memória física que está sendo usada por outro
processo ou pelo sistema operacional.
O intervalo de endereços virtuais que está disponível para um processo é conhecido
como espaço de endereço virtual do processo. Cada processo de modo de usuário tem
seu próprio espaço de endereço virtual privado.
Um processo de 32 bits normalmente tem um espaço de endereço virtual dentro
do intervalo de 2 gigabytes 0x00000000 até 0x7FFFFFFF.
Um processo de 64 bits no Windows de 64 bits tem um espaço de endereço virtual
dentro do intervalo de 128 terabytes 0x000'000000000 até 0x7FFF'FFFFFFFF.
Um intervalo de endereços virtuais às vezes é chamado de intervalo de memória virtual.
Para obter mais informações, consulte Limites de memória e espaço de endereço.
O diagrama a seguir ilustra alguns dos principais recursos de espaços de endereço
virtuais.
O diagrama mostra os espaços de endereço virtual para dois processos de 64 bits:
[Link] e [Link]. Cada processo tem seu próprio espaço de endereço virtual,
variando de 0x000'0000000 a 0x7FF'FFFFFFFF. Cada bloco sombreado representa uma
página (4 quilobytes de tamanho) de memória virtual ou física. O processo do Bloco de
Notas usa três páginas contíguas de endereços virtuais, começando em
0x7F7'93950000. No entanto, essas três páginas contíguas de endereços virtuais são
mapeadas para páginas não contíguas na memória física. Além disso, ambos os
processos usam uma página de memória virtual começando em 0x7F7'93950000, mas
essas páginas virtuais são mapeadas para páginas diferentes de memória física.
Espaço do usuário e espaço do sistema
Processos como [Link] e [Link] são executados no modo de usuário. Os
principais componentes do sistema operacional e muitos drivers são executados no
modo kernel mais privilegiado. Para obter mais informações sobre modos de
processador, consulte Modo de usuário e modo kernel.
Cada processo de modo de usuário tem seu próprio espaço de endereço virtual privado,
mas todo o código executado no modo kernel compartilha um único espaço de
endereço virtual chamado espaço do sistema. O espaço de endereço virtual para um
processo de modo de usuário é chamado de espaço do usuário.
No Windows de 32 bits, o espaço de endereço virtual disponível total é de 2^32 bytes
(4 gigabytes). Normalmente, os 2 gigabytes inferiores são usados para o espaço do
usuário e os 2 gigabytes superiores são usados para o espaço do sistema.
No Windows de 32 bits, você pode especificar (no momento da inicialização) que mais
de 2 gigabytes estão disponíveis para o espaço do usuário. No entanto, isso significa
que menos endereços virtuais estão disponíveis para o espaço do sistema. Você pode
aumentar o tamanho do espaço do usuário para até 3 gigabytes, deixando apenas 1
gigabyte para o espaço do sistema. Para aumentar o tamanho do espaço do usuário,
use BCDEdit /set increaseuserva.
No Windows de 64 bits, a quantidade teórica de espaço de endereço virtual é de 2^64
bytes (16 exabytes), mas apenas uma pequena parte do intervalo de 16 exabytes é
realmente usada.
O código em execução no modo de usuário pode acessar o espaço do usuário, mas não
o espaço do sistema. Essa restrição impede que o código do modo de usuário leia ou
altere estruturas de dados do sistema operacional protegido. O código em execução no
modo kernel pode acessar o espaço do usuário e o espaço do sistema. Ou seja, o
código em execução no modo kernel pode acessar o espaço do sistema e o espaço de
endereço virtual do processo atual do modo de usuário.
Os drivers em execução no modo kernel devem ter cuidado ao ler diretamente ou
gravar em endereços no espaço do usuário. O cenário a seguir ilustra o motivo.
1. Um programa de modo de usuário inicia uma solicitação para ler alguns dados de
um dispositivo. O programa fornece o endereço inicial de um buffer para receber
os dados.
2. Uma rotina de driver de dispositivo, em execução no modo kernel, inicia a
operação de leitura e retorna o controle ao chamador.
3. Posteriormente, o dispositivo interrompe o thread em execução no momento para
indicar que a operação de leitura foi concluída. As rotinas de driver no modo
kernel lidam com a interrupção nesse thread arbitrário, que pertence a um
processo arbitrário.
4. Neste ponto, o driver não deve gravar os dados no endereço inicial que o
programa de modo de usuário forneceu na Etapa 1. Esse endereço está no espaço
de endereço virtual do processo que iniciou a solicitação, o que provavelmente
não é o mesmo que o processo atual.
Pool paginado e pool nãopagado
No espaço do usuário, todas as páginas de memória física podem ser paginada em um
arquivo de disco, conforme necessário. No espaço do sistema, algumas páginas físicas
podem ser paginada e outras não. O espaço do sistema tem duas regiões para alocar
memória dinamicamente: pool paginado e pool nãopagado.
A memória alocada no pool paginado pode ser paginada em um arquivo de disco,
conforme necessário. A memória alocada no pool nãopagado nunca pode ser paginada
em um arquivo de disco.
Tópicos relacionados
Nós de dispositivo e pilhas de dispositivos
Modo de usuário e modo kernel
Comentários
Esta página foi útil? Yes No
Fornecer comentários sobre o produto | Obter ajuda no Microsoft Q&A
Nós de dispositivo e pilhas de
dispositivos
Artigo • 29/06/2024
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.
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 [Link] do driver, o objeto de
dispositivo do meio está associado ao [Link] do driver e o objeto de dispositivo
inferior está associado ao [Link] 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 [Link] e um objeto de dispositivo associado a
[Link].
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 ([Link]) para enumerar os
dispositivos que estão conectados ao barramento PCI. Em resposta a essa solicitação,
[Link] 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 [Link] cria o conjunto de PDOs, a árvore de dispositivos se parece
com a mostrada no diagrama a seguir.
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.
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 [Link] desempenha duas funções.
Primeiro, [Link] está associado ao FDO no nó do dispositivo PCI Bus. Na verdade, ele
criou o FDO no nó do dispositivo PCI Bus. Portanto, [Link] é o driver de função para o
barramento PCI. Em segundo lugar, [Link] 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 [Link] é o driver de função. Mas
se o seu ponto de referência é o dispositivo Proseware Gizmo, então [Link] é 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.
Artigos relacionados
Conceitos para todos os desenvolvedores de drivers
Pilhas de drivers
Comentários
Esta página foi útil? Yes No
Fornecer comentários sobre o produto | Obter ajuda no Microsoft Q&A
Pacotes de solicitação de E/S
Artigo • 04/10/2024
A maioria das solicitações enviadas aos drivers de dispositivo é empacotada em pacotes
de solicitação de E/S (IRPs). Um componente do sistema operacional ou um driver envia
um IRP para um driver chamando IoCallDriver, que tem dois parâmetros: um ponteiro
para um DEVICE_OBJECT e um ponteiro para um IRP. O DEVICE_OBJECT tem um
ponteiro para um DRIVER_OBJECT associado. Quando um componente chama
IoCallDriver, dizemos que o componente envia o IRP para o objeto do dispositivo ou
envia o IRP para o driver associado ao objeto de dispositivo. Às vezes, usamos a frase
passa o IRP ou encaminha o IRP em vez de envia o IRP.
Normalmente, um IRP é processado por vários drivers organizados em uma pilha. Cada
driver na pilha está associado a um objeto de dispositivo. Para obter mais informações,
consulte Nós de dispositivo e pilhas de dispositivos. Quando um IRP é processado por
uma pilha de dispositivos, o IRP geralmente é enviado primeiro para o objeto de
dispositivo superior na pilha de dispositivos. Por exemplo, se um IRP for processado
pela pilha de dispositivos mostrada neste diagrama, o IRP será enviado primeiro para o
objeto de dispositivo de filtro (Filtro DO) na parte superior da pilha de dispositivos.
Passar de um IRP para a pilha do dispositivo
Suponha que o gerenciador de E/S envie um IRP para o Filtro DO no diagrama. O driver
associado ao Filtro DO, [Link], processa o IRP e, em seguida, o passa para o
FDO (objeto de dispositivo funcional), que é o próximo objeto de dispositivo inferior na
pilha de dispositivos. Quando um driver passa um IRP para o próximo objeto de
dispositivo inferior na pilha de dispositivos, dizemos que o driver passa o IRP para baixo
na pilha de dispositivos.
Alguns IRPs são passados por toda a pilha de dispositivos para o PDO (objeto de
dispositivo físico). Outros IRPs nunca alcançam o PDO porque são concluídos por um
dos drivers acima do PDO.
IRPs são autossuficientes
A estrutura do IRP é autossuficiente no sentido de que contém todas as informações de
que um driver precisa para lidar com uma solicitação de E/S. Algumas partes da
estrutura do IRP contêm informações comuns a todos os drivers participantes na pilha.
Outras partes do IRP contêm informações específicas de um driver específico na pilha.
Comentários
Esta página foi útil? Yes No
Fornecer comentários sobre o produto | Obter ajuda no Microsoft Q&A
Pilhas de drivers
Artigo • 29/06/2024
A maioria das solicitações enviadas aos drivers de dispositivo são empacotadas em
pacotes de solicitação de E/S (IRPs). Cada dispositivo é representado por um nó de
dispositivo e cada nó de dispositivo tem uma pilha de dispositivos. Para obter mais
informações, consulte Nós de dispositivo e pilhas de dispositivos. Para enviar uma
solicitação de leitura, gravação ou controle para um dispositivo, o gerenciador de E/S
localiza o nó do dispositivo para o dispositivo e, em seguida, envia um IRP para a pilha
de dispositivos desse nó. Às vezes, mais de uma pilha de dispositivos está envolvida no
processamento de uma solicitação de E/S. Independentemente de quantas pilhas de
dispositivos estão envolvidas, a sequência geral de drivers que participam de uma
solicitação de E/S é chamada de pilha de driver para a solicitação. Também usamos o
termo pilha de drivers para nos referirmos ao conjunto de drivers em camadas para uma
tecnologia específica.
Solicitações de E/S processadas por várias
pilhas de dispositivos
Em alguns casos, mais de uma pilha de dispositivos está envolvida no processamento de
uma IRP. O diagrama a seguir ilustra um caso em que quatro pilhas de dispositivos
estão envolvidas no processamento de um único IRP.
Veja como o IRP é processado em cada estágio numerado no diagrama:
1. O IRP é criado por [Link], que é o driver de função na pilha de dispositivos para
o nó Meu dispositivo de armazenamento USB. [Link] passa o IRP pela pilha de
dispositivos para [Link].
2. Observe que [Link] é o driver PDO para o nó Meu dispositivo de
armazenamento USB e o driver FDO para o nó Dispositivo de armazenamento em
massa USB. Neste ponto, não é importante decidir se o IRP pertence ao par (PDO,
[Link]) ou ao par (FDO, [Link]). O IRP é de propriedade do motorista,
[Link], e o driver tem acesso ao PDO e ao FDO.
3. Quando [Link] terminar de processar o IRP, ele passa o IRP para [Link].
[Link] é o driver PDO para o nó USB Mass Storage Device e o driver FDO para
o nó USB Root Hub. Não é importante decidir se o IRP pertence ao par (PDO,
[Link]) ou ao par (FDO, [Link]). O IRP é de propriedade do motorista,
[Link], e o motorista tem acesso ao PDO e ao FDO.
4. Quando [Link] terminar de processar o IRP, ele passa o IRP para o par
([Link], [Link]).
[Link] é um driver de miniporta e [Link] é um driver de porta. O par
(miniport, port) desempenha o papel de um único driver. Nesse caso, o driver de
miniporta e o driver de porta são escritos pela Microsoft. O par ([Link],
[Link]) é o driver PDO para o nó USB Root Hub, e o par ([Link],
[Link]) também é o driver FDO para o nó USB Host Controller. O par
([Link], [Link]) faz a comunicação real com o hardware do controlador
host, que por sua vez se comunica com o dispositivo de armazenamento USB
físico.
A pilha de drivers para uma solicitação de E/S
Considere a sequência de quatro drivers que participaram da solicitação de E/S ilustrada
no diagrama anterior. Podemos obter outra visão da sequência concentrando-nos nos
drivers em vez de nos nós do dispositivo e suas pilhas de dispositivos individuais. O
diagrama a seguir mostra os drivers em sequência de cima para baixo. Observe que
[Link] está associado a um objeto de dispositivo, mas cada um dos outros três drivers
está associado a dois objetos de dispositivo.
A sequência de drivers que participam de uma solicitação de E/S é chamada de pilha de
driver para a solicitação de E/S. Para ilustrar uma pilha de drivers para uma solicitação de
E/S, desenhamos os drivers de cima para baixo na ordem em que eles participam da
solicitação.
Observe que a pilha de driver para uma solicitação de E/S é bem diferente da pilha de
dispositivos para um nó de dispositivo. Observe também que a pilha de driver para uma
solicitação de E/S não permanece necessariamente em uma ramificação da árvore de
dispositivos.
Pilhas de drivers de tecnologia
Considere a pilha de driver para a solicitação de E/S mostrada no diagrama anterior. Se
dermos a cada um dos drivers um nome amigável e fizermos algumas pequenas
alterações no diagrama, teremos um diagrama de blocos semelhante a muitos dos que
aparecem na documentação do Windows Driver Kit (WDK).
No diagrama, a pilha de drivers é dividida em três seções. Podemos pensar em cada
seção como pertencente a uma tecnologia específica ou a um componente ou parte
específica do sistema operacional. Por exemplo, podemos dizer que a primeira seção na
parte superior da pilha de drivers pertence ao Gerenciador de Volumes, a segunda
seção pertence ao componente de armazenamento do sistema operacional e a terceira
seção pertence à parte USB principal do sistema operacional.
Considere os drivers na terceira seção. Esses drivers são um subconjunto de um
conjunto maior de drivers USB principais que a Microsoft fornece para lidar com vários
tipos de solicitações USB e hardware USB. O diagrama a seguir mostra a aparência de
todo o diagrama de blocos de núcleo USB.
Um diagrama de blocos que mostra todos os drivers para uma tecnologia específica ou
um componente específico ou parte do sistema operacional é chamado de pilha de
drivers de tecnologia. Normalmente, as pilhas de drivers de tecnologia recebem nomes
como a pilha de drivers USB Core, a pilha de armazenamento, a pilha de drivers 1394 e a
pilha de drivers de áudio.
Nota: O diagrama de bloco de núcleo USB neste artigo mostra uma das várias maneiras
possíveis de ilustrar as pilhas de driver de tecnologia para USB 1.0 e 2.0. Para obter os
diagramas oficiais das pilhas de drivers USB 1.0, 2.0 e 3.0, consulte USB Driver Stack
Architecture.
Artigos relacionados
Nós de dispositivo e pilhas de dispositivos
Minidrivers e pares de drivers
Conceitos para todos os desenvolvedores de drivers
Comentários
Esta página foi útil? Yes No
Fornecer comentários sobre o produto | Obter ajuda no Microsoft Q&A
Minidrivers, drivers miniport e pares de
motoristas
Artigo • 27/09/2024
Um minidriver ou um motorista de miniporta atua como metade de um par de
motoristas. Pares de driver como (miniport, porta) podem facilitar o desenvolvimento do
driver. Em um par de drivers, um driver lida com tarefas gerais que são comuns a uma
coleção inteira de dispositivos, enquanto o outro driver lida com tarefas específicas de
um dispositivo individual. Os drivers que lidam com tarefas específicas do dispositivo
passam por uma variedade de nomes, incluindo driver de miniporta, driver de miniclasse
e minidriver.
A Microsoft fornece o driver geral e, normalmente, um fornecedor de hardware
independente fornece o driver específico. Antes de ler este tópico, você deve entender
as ideias apresentadas em Nós de dispositivo e pilhas de dispositivos e pacotes de
solicitação de E/S.
Cada driver de modo kernel deve implementar uma função chamada DriverEntry, que é
chamada logo após o driver ser carregado. A função DriverEntry preenche
determinados membros de uma estrutura DRIVER_OBJECT com ponteiros para várias
outras funções que o driver implementa. Por exemplo, a função DriverEntry preenche o
membro Unload da estrutura DRIVER_OBJECT com um ponteiro para a função Unload
do driver, conforme mostrado no diagrama a seguir.
O membro MajorFunction da estrutura DRIVER_OBJECT é uma matriz de ponteiros para
funções que lidam com pacotes de solicitação de E/S (IRPs), conforme mostrado no
diagrama a seguir. Normalmente, o driver preenche vários membros da matriz
MajorFunction com ponteiros para funções (implementadas pelo driver) que lidam com
vários tipos de IRPs.
Um IRP pode ser categorizado de acordo com seu código de função principal, que é
identificado por uma constante, como IRP_MJ_READ, IRP_MJ_WRITE ou IRP_MJ_PNP.
As constantes que identificam o código de função principal servem como índices na
matriz MajorFunction . Por exemplo, suponha que o driver implemente uma função de
expedição para lidar com IRPs que têm o código de função principal IRP_MJ_WRITE.
Nesse caso, o driver deve preencher o elemento MajorFunction[IRP_MJ_WRITE] da
matriz com um ponteiro para a função dispatch.
Normalmente, o driver preenche alguns dos elementos da matriz MajorFunction e deixa
os elementos restantes definidos como valores padrão fornecidos pelo gerenciador de
E/S. O exemplo a seguir mostra como usar a extensão do depurador !drvobj para
inspecionar os ponteiros de função para o driver de relatório.
syntax
0: kd> !drvobj parport 2
Driver object (fffffa80048d9e70) is for:
\Driver\Parport
DriverEntry: fffff880065ea070 parport!GsDriverEntry
DriverStartIo: 00000000
DriverUnload: fffff880065e131c parport!PptUnload
AddDevice: fffff880065d2008 parport!P5AddDevice
Dispatch routines:
[00] IRP_MJ_CREATE fffff880065d49d0
parport!PptDispatchCreateOpen
[01] IRP_MJ_CREATE_NAMED_PIPE fffff80001b6ecd4
nt!IopInvalidDeviceRequest
[02] IRP_MJ_CLOSE fffff880065d4a78
parport!PptDispatchClose
[03] IRP_MJ_READ fffff880065d4bac
parport!PptDispatchRead
[04] IRP_MJ_WRITE fffff880065d4bac
parport!PptDispatchRead
[05] IRP_MJ_QUERY_INFORMATION fffff880065d4c40
parport!PptDispatchQueryInformation
[06] IRP_MJ_SET_INFORMATION fffff880065d4ce4
parport!PptDispatchSetInformation
[07] IRP_MJ_QUERY_EA fffff80001b6ecd4
nt!IopInvalidDeviceRequest
[08] IRP_MJ_SET_EA fffff80001b6ecd4
nt!IopInvalidDeviceRequest
[09] IRP_MJ_FLUSH_BUFFERS fffff80001b6ecd4
nt!IopInvalidDeviceRequest
[0a] IRP_MJ_QUERY_VOLUME_INFORMATION fffff80001b6ecd4
nt!IopInvalidDeviceRequest
[0b] IRP_MJ_SET_VOLUME_INFORMATION fffff80001b6ecd4
nt!IopInvalidDeviceRequest
[0c] IRP_MJ_DIRECTORY_CONTROL fffff80001b6ecd4
nt!IopInvalidDeviceRequest
[0d] IRP_MJ_FILE_SYSTEM_CONTROL fffff80001b6ecd4
nt!IopInvalidDeviceRequest
[0e] IRP_MJ_DEVICE_CONTROL fffff880065d4be8
parport!PptDispatchDeviceControl
[0f] IRP_MJ_INTERNAL_DEVICE_CONTROL fffff880065d4c24
parport!PptDispatchInternalDeviceControl
[10] IRP_MJ_SHUTDOWN fffff80001b6ecd4
nt!IopInvalidDeviceRequest
[11] IRP_MJ_LOCK_CONTROL fffff80001b6ecd4
nt!IopInvalidDeviceRequest
[12] IRP_MJ_CLEANUP fffff880065d4af4
parport!PptDispatchCleanup
[13] IRP_MJ_CREATE_MAILSLOT fffff80001b6ecd4
nt!IopInvalidDeviceRequest
[14] IRP_MJ_QUERY_SECURITY fffff80001b6ecd4
nt!IopInvalidDeviceRequest
[15] IRP_MJ_SET_SECURITY fffff80001b6ecd4
nt!IopInvalidDeviceRequest
[16] IRP_MJ_POWER fffff880065d491c
parport!PptDispatchPower
[17] IRP_MJ_SYSTEM_CONTROL fffff880065d4d4c
parport!PptDispatchSystemControl
[18] IRP_MJ_DEVICE_CHANGE fffff80001b6ecd4
nt!IopInvalidDeviceRequest
[19] IRP_MJ_QUERY_QUOTA fffff80001b6ecd4
nt!IopInvalidDeviceRequest
[1a] IRP_MJ_SET_QUOTA fffff80001b6ecd4
nt!IopInvalidDeviceRequest
[1b] IRP_MJ_PNP fffff880065d4840
parport!PptDispatchPnp
Na saída do depurador, você pode ver que [Link] implementa GsDriverEntry, o
ponto de entrada do driver. GsDriverEntry, que foi gerado automaticamente quando o
driver foi criado, executa alguma inicialização e, em seguida, chama DriverEntry, que foi
implementado pelo desenvolvedor do driver.
Você também pode ver que o driver de parport (em sua função DriverEntry ) fornece
ponteiros para expedir funções para esses códigos de função principais:
IRP_MJ_CREATE
IRP_MJ_CLOSE
IRP_MJ_READ
IRP_MJ_WRITE
IRP_MJ_QUERY_INFORMATION
IRP_MJ_SET_INFORMATION
IRP_MJ_DEVICE_CONTROL
IRP_MJ_INTERNAL_DEVICE_CONTROL
IRP_MJ_CLEANUP
IRP_MJ_POWER
IRP_MJ_SYSTEM_CONTROL
IRP_MJ_PNP
Os elementos restantes da matriz MajorFunction mantêm ponteiros para a função de
expedição padrão nt! IopInvalidDeviceRequest.
Na saída do depurador, você pode ver que o driver de parport forneceu ponteiros de
função para Unload e AddDevice, mas não forneceu um ponteiro de função para StartIo.
A função AddDevice é incomum porque seu ponteiro de função não é armazenado na
estrutura DRIVER_OBJECT . Em vez disso, ele é armazenado no membro AddDevice de
uma extensão para a estrutura DRIVER_OBJECT . O diagrama a seguir ilustra os
ponteiros de função fornecidos pelo driver de portabilidade em sua função DriverEntry .
Os ponteiros de função fornecidos pelo parport são sombreados.
Facilitando o uso de pares de driver
Durante um período de tempo, como desenvolvedores de driver dentro e fora da
Microsoft ganharam experiência com o Modelo de Driver do Windows (WDM), eles
perceberam algumas coisas sobre funções de expedição:
As funções de expedição são em grande parte clichês. Por exemplo, grande parte
do código na função de expedição para IRP_MJ_PNP é o mesmo para todos os
drivers. É apenas uma pequena parte do código de Plug and Play (PnP) que é
específica para um driver individual que controla uma parte individual do
hardware.
As funções de expedição são complicadas e difíceis de acertar. Implementar
recursos como sincronização de thread, enfileiramento de IRP e cancelamento de
IRP é um desafio e requer uma compreensão profunda de como o sistema
operacional funciona.
Para facilitar as coisas para desenvolvedores de driver, a Microsoft criou vários modelos
de driver específicos da tecnologia. À primeira vista, os modelos específicos da
tecnologia parecem bem diferentes uns dos outros, mas um olhar mais atento revela
que muitos deles se baseiam nesse paradigma:
O driver é dividido em duas partes: uma que manipula o processamento geral e
outra que manipula o processamento específico de um dispositivo específico.
A peça geral é escrita pela Microsoft.
A peça específica pode ser escrita pela Microsoft ou por um fornecedor de
hardware independente.
Suponha que as empresas Proseware e Contoso criem um robô de toy que exija um
driver WDM. Suponha também que a Microsoft forneça um Driver Robô Geral chamado
[Link]. A Proseware e a Contoso podem escrever pequenos drivers que lidam
com os requisitos de seus robôs específicos. Por exemplo, a Proseware poderia escrever
[Link] e o par de drivers ([Link], [Link]) poderia
ser combinado para formar um único driver WDM. Da mesma forma, o par de drivers
([Link], [Link]) poderia ser combinado para formar um único
driver WDM. Em sua forma mais geral, a ideia é que você possa criar drivers usando
pares ([Link], [Link]).
Ponteiros de função em pares de driver
Em um par ([Link], [Link]), o Windows carrega [Link] e chama sua função
DriverEntry . A função DriverEntry de [Link] recebe um ponteiro para uma
estrutura DRIVER_OBJECT . Normalmente, você esperaria que DriverEntry preenchesse
vários elementos da matriz MajorFunction com ponteiros para expedir funções. Além
disso, você esperaria que DriverEntry preenchesse o membro Unload (e possivelmente
o membro StartIo ) da estrutura DRIVER_OBJECT e o membro AddDevice da extensão
do objeto driver. No entanto, em um modelo de par de driver, DriverEntry não
necessariamente faz isso. Em vez disso, a função DriverEntry de [Link] passa a
estrutura DRIVER_OBJECT para uma função de inicialização implementada por
[Link]. O exemplo de código a seguir mostra como a função de inicialização pode
ser chamada no par ([Link], [Link]).
ManagedCPlusPlus
PVOID g_ProsewareRobottCallbacks[3] = {DeviceControlCallback, PnpCallback,
PowerCallback};
// DriverEntry function in [Link]
NTSTATUS DriverEntry (DRIVER_OBJECT *DriverObject, PUNICODE_STRING
RegistryPath)
{
// Call the initialization function implemented by [Link].
return GeneralRobotInit(DriverObject, RegistryPath,
g_ProsewareRobottCallbacks);
}
A função de inicialização no [Link] grava ponteiros de função para os
membros apropriados da estrutura de DRIVER_OBJECT (e sua extensão) e os elementos
apropriados da matriz MajorFunction . A ideia é que, quando o gerente de E/S envia um
IRP para o par de driver, o IRP vai primeiro para uma função de expedição
implementada por [Link]. Se [Link] puder lidar com o IRP por
conta própria, o driver específico, [Link], não precisará estar envolvido. Se
[Link] puder lidar com alguns, mas não todos, do processamento de IRP, ele
obterá ajuda de uma das funções de retorno de chamada implementadas por
[Link]. [Link] recebe ponteiros para os retornos de chamada
prosewareRobot na chamada GeneralRobotInit.
Em algum momento após o retorno de DriverEntry , uma pilha de dispositivos é
construída para o nó do dispositivo Proseware Robot. A pilha do dispositivo pode ter
esta aparência.
Conforme mostrado no diagrama anterior, a pilha de dispositivos para o Proseware
Robot tem três objetos de dispositivo. O objeto de dispositivo superior é um objeto de
dispositivo de filtro (Filter DO) associado ao driver de filtro [Link]. O objeto
de dispositivo intermediário é um FDO (objeto de dispositivo funcional) associado ao
par de driver ([Link], [Link]). O par de driver serve como o
driver de função para a pilha do dispositivo. O objeto de dispositivo inferior é um PDO
(objeto de dispositivo físico) associado a [Link].
Observe que o par de driver ocupa apenas um nível na pilha do dispositivo e está
associado a apenas um objeto de dispositivo: o FDO. Quando [Link]
processa um IRP, ele pode chamar [Link] para obter assistência, mas isso
não é o mesmo que passar a solicitação para baixo na pilha do dispositivo. O par de
driver forma um único driver WDM que está em um nível na pilha do dispositivo. O par
de drivers conclui o IRP ou passa-o para baixo na pilha do dispositivo para o PDO, que
está associado a [Link].
Exemplo de um par de drivers
Suponha que você tenha uma rede sem fio cartão em seu computador laptop e
examinando Gerenciador de Dispositivos, determine que [Link] é o driver do
cartão de rede. Você pode usar a extensão do depurador !drvobj para inspecionar os
ponteiros de função para [Link].
syntax
1: kd> !drvobj netwlv64 2
Driver object (fffffa8002e5f420) is for:
\Driver\netwlv64
DriverEntry: fffff8800482f064 netwlv64!GsDriverEntry
DriverStartIo: 00000000
DriverUnload: fffff8800195c5f4 ndis!ndisMUnloadEx
AddDevice: fffff88001940d30 ndis!ndisPnPAddDevice
Dispatch routines:
[00] IRP_MJ_CREATE fffff880018b5530
ndis!ndisCreateIrpHandler
[01] IRP_MJ_CREATE_NAMED_PIPE fffff88001936f00
ndis!ndisDummyIrpHandler
[02] IRP_MJ_CLOSE fffff880018b5870
ndis!ndisCloseIrpHandler
[03] IRP_MJ_READ fffff88001936f00
ndis!ndisDummyIrpHandler
[04] IRP_MJ_WRITE fffff88001936f00
ndis!ndisDummyIrpHandler
[05] IRP_MJ_QUERY_INFORMATION fffff88001936f00
ndis!ndisDummyIrpHandler
[06] IRP_MJ_SET_INFORMATION fffff88001936f00
ndis!ndisDummyIrpHandler
[07] IRP_MJ_QUERY_EA fffff88001936f00
ndis!ndisDummyIrpHandler
[08] IRP_MJ_SET_EA fffff88001936f00
ndis!ndisDummyIrpHandler
[09] IRP_MJ_FLUSH_BUFFERS fffff88001936f00
ndis!ndisDummyIrpHandler
[0a] IRP_MJ_QUERY_VOLUME_INFORMATION fffff88001936f00
ndis!ndisDummyIrpHandler
[0b] IRP_MJ_SET_VOLUME_INFORMATION fffff88001936f00
ndis!ndisDummyIrpHandler
[0c] IRP_MJ_DIRECTORY_CONTROL fffff88001936f00
ndis!ndisDummyIrpHandler
[0d] IRP_MJ_FILE_SYSTEM_CONTROL fffff88001936f00
ndis!ndisDummyIrpHandler
[0e] IRP_MJ_DEVICE_CONTROL fffff8800193696c
ndis!ndisDeviceControlIrpHandler
[0f] IRP_MJ_INTERNAL_DEVICE_CONTROL fffff880018f9114
ndis!ndisDeviceInternalIrpDispatch
[10] IRP_MJ_SHUTDOWN fffff88001936f00
ndis!ndisDummyIrpHandler
[11] IRP_MJ_LOCK_CONTROL fffff88001936f00
ndis!ndisDummyIrpHandler
[12] IRP_MJ_CLEANUP fffff88001936f00
ndis!ndisDummyIrpHandler
[13] IRP_MJ_CREATE_MAILSLOT fffff88001936f00
ndis!ndisDummyIrpHandler
[14] IRP_MJ_QUERY_SECURITY fffff88001936f00
ndis!ndisDummyIrpHandler
[15] IRP_MJ_SET_SECURITY fffff88001936f00
ndis!ndisDummyIrpHandler
[16] IRP_MJ_POWER fffff880018c35e8
ndis!ndisPowerDispatch
[17] IRP_MJ_SYSTEM_CONTROL fffff880019392c8
ndis!ndisWMIDispatch
[18] IRP_MJ_DEVICE_CHANGE fffff88001936f00
ndis!ndisDummyIrpHandler
[19] IRP_MJ_QUERY_QUOTA fffff88001936f00
ndis!ndisDummyIrpHandler
[1a] IRP_MJ_SET_QUOTA fffff88001936f00
ndis!ndisDummyIrpHandler
[1b] IRP_MJ_PNP fffff8800193e518
ndis!ndisPnPDispatch
Na saída do depurador, você pode ver que [Link] implementa GsDriverEntry, o
ponto de entrada do driver. GsDriverEntry, que foi gerado automaticamente quando o
driver foi criado, executa alguma inicialização e chama DriverEntry, que foi escrito pelo
desenvolvedor do driver.
Neste exemplo, [Link] implementa DriverEntry, mas [Link] implementa
AddDevice, Unload e várias funções de expedição. [Link] é chamado de driver de
miniporta NDIS e [Link] é chamada de Biblioteca NDIS. Juntos, os dois módulos
formam um par (miniporto NDIS, Biblioteca NDIS).
Este diagrama mostra a pilha de dispositivos para o cartão de rede sem fio. Observe que
o par de drivers ([Link], [Link]) ocupa apenas um nível na pilha do dispositivo e
está associado a apenas um objeto de dispositivo: o FDO.
Pares de driver disponíveis
Os diferentes modelos de driver específicos da tecnologia usam uma variedade de
nomes para as partes específicas e gerais de um par de drivers. Em muitos casos, a parte
específica do par tem o prefixo "mini". Aqui estão alguns dos pares (específicos, gerais)
que estão disponíveis:
(exibir driver de miniporta, exibir driver de porta)
(driver de miniporta de áudio, driver de porta de áudio)
(driver de miniporta de armazenamento, driver de porta de armazenamento)
(driver de miniclasse de bateria, driver de classe de bateria)
(Minidriver HID, driver de classe HID)
(driver de miniclasse do alterador, driver de porta do alterador)
(Driver de miniporta NDIS, biblioteca NDIS)
Nota Como você pode ver na lista, vários dos modelos usam o termo driver de classe
para a parte geral de um par de drivers. Esse tipo de driver de classe é diferente de um
driver de classe autônomo e diferente de um driver de filtro de classe.
Tópicos relacionados
Conceitos para todos os desenvolvedores de driver
Nós de dispositivo e pilhas de dispositivos
Pilhas de driver
Comentários
Esta página foi útil? Yes No
Fornecer comentários sobre o produto | Obter ajuda no Microsoft Q&A
KMDF como um modelo de par de
driver genérico
Artigo • 01/02/2024
Neste tópico, discutiremos a ideia de que a Estrutura de Driver do Modo Kernel pode
ser vista como um modelo de par de driver genérico. Antes de ler este tópico, você deve
entender as ideias apresentadas em minidrivers e pares de driver.
Ao longo dos anos, a Microsoft criou vários modelos de driver específicos da tecnologia
que usam esse paradigma:
O driver é dividido em duas partes: uma que manipula o processamento geral e
outra que manipula o processamento específico de um dispositivo específico.
A peça geral, chamada Framework, é escrita pela Microsoft.
A peça específica, chamada driver KMDF, pode ser escrita pela Microsoft ou por
um fornecedor de hardware independente.
A parte Framework do par de driver executa tarefas gerais que são comuns a uma ampla
variedade de drivers. Por exemplo, a Estrutura pode lidar com filas de solicitação de E/S,
sincronização de threads e uma grande parte das tarefas de gerenciamento de energia.
A Estrutura é proprietária da tabela de expedição do driver KMDF, portanto, quando
alguém envia um IRP (pacote de solicitação de E/S) para o par (driver KMDF,
Framework), o IRP vai para Framework. Se a Estrutura puder lidar com o IRP por si só, o
driver KMDF não estará envolvido. Se a Estrutura não puder manipular o IRP por si só,
ela obterá ajuda chamando manipuladores de eventos implementados pelo driver
KMDF. Aqui estão alguns exemplos de manipuladores de eventos que podem ser
implementados por um driver KMDF.
EvtDevicePrepareHardware
EvtIoRead
EvtIoDeviceControl
EvtInterruptIsr
EvtInterruptDpc
EvtDevicePnpStateChange
Por exemplo, um driver de controlador de host USB 2.0 tem uma peça específica
chamada [Link] e uma peça geral chamada [Link]. [Link], que é
chamado de driver usb 2.0 Miniport, tem um código específico para controladores de
host USB 2.0. [Link], que é chamado de driver de porta USB, tem código geral que
se aplica a USB 2.0 e USB 1.0. O par de drivers ([Link], [Link]) combinam para
formar um único driver WDM para um controlador de host USB 2.0.
Os pares de driver (específicos, gerais) têm uma variedade de nomes em diferentes
tecnologias de dispositivo. A maioria dos drivers específicos do dispositivo tem o prefixo
mini. Os drivers gerais geralmente são chamados de drivers de porta ou classe. Aqui
estão alguns exemplos de pares (específicos, gerais):
(exibir driver de miniporta, exibir driver de porta)
(Driver de miniporta USB, driver de porta USB)
(driver de miniclasse de bateria, driver de classe de bateria)
(Minidriver HID, driver de classe HID)
(driver de miniporta de armazenamento, driver de porta de armazenamento)
À medida que mais e mais modelos de pares de motoristas foram desenvolvidos,
tornou-se difícil acompanhar todas as diferentes maneiras de escrever um driver. Cada
modelo tem sua própria interface para comunicação entre o driver específico do
dispositivo e o driver geral. O corpo de conhecimento necessário para desenvolver
drivers para uma tecnologia de dispositivo (por exemplo, Áudio) pode ser bem diferente
do corpo de conhecimento necessário para desenvolver drivers para outra tecnologia de
dispositivo (por exemplo, Armazenamento).
Com o tempo, os desenvolvedores perceberam que seria bom ter um único modelo
unificado para pares de driver no modo kernel. A KMDF (Estrutura de Driver do Modo
Kernel), que estava disponível pela primeira vez no Windows Vista, atende a essa
necessidade. Um driver baseado no KMDF usa um paradigma semelhante a muitos dos
modelos de par de drivers específicos da tecnologia.
O driver é dividido em duas partes: uma que manipula o processamento geral e
outra que manipula o processamento específico de um dispositivo específico.
A peça geral, que é escrita pela Microsoft, é chamada de Estrutura.
A peça específica, que é escrita pela Microsoft ou por um fornecedor
independente de hardware, é chamada de driver KMDF.
O driver do controlador de host USB 3.0 é um exemplo de um driver baseado em KMDF.
Neste exemplo, ambos os drivers no par são escritos pela Microsoft. O driver geral é a
Estrutura e o driver específico do dispositivo é o Driver do Controlador de Host USB 3.0.
Este diagrama ilustra o nó do dispositivo e a pilha de dispositivos para um controlador
de host USB 3.0.
No diagrama, [Link] é o driver do controlador de host USB 3.0. Ele é emparelhado
com [Link], que é a Estrutura. O par ([Link], [Link]) forma um único
driver WDM que serve como o driver de função para o controlador de host USB 3.0.
Observe que o par de driver ocupa um nível na pilha do dispositivo e é representado
por um único objeto de dispositivo. O único objeto de dispositivo que representa o par
([Link], [Link]) é o FDO (objeto de dispositivo funcional) para o controlador
de host USB 3.0.
Em um par (driver KMDF, Framework), o Framework lida com tarefas que são comuns a
uma ampla variedade de drivers no modo kernel. Por exemplo, a Estrutura pode lidar
com o enfileiramento de solicitações de E/S, sincronização de threads, a maioria das
tarefas de Plug and Play e a maioria das tarefas de gerenciamento de energia. O driver
KMDF lida com tarefas que exigem interação com um dispositivo específico. O driver
KMDF participa do processamento de solicitações registrando manipuladores de
eventos que o Framework chama conforme necessário.
Tópicos relacionados
Minidrivers e pares de drivers
Estrutura do driver do modo Kernel
Comentários
Esta página foi útil? Yes No
Fornecer comentários sobre o produto | Obter ajuda no Microsoft Q&A
Extensões KMDF e triplos de driver
Artigo • 01/02/2024
Neste tópico, discutiremos extensões baseadas em classe para o KMDF (Kernel Mode
Driver Framework). Antes de ler este tópico, você deve entender as ideias apresentadas
em minidrivers e pares de driver e KMDF como um modelo de par de driver genérico.
Para algumas classes de dispositivo, a Microsoft fornece extensões KMDF que reduzem
ainda mais a quantidade de processamento que deve ser executada por drivers KMDF.
Um driver que usa uma extensão KMDF baseada em classe tem essas três partes, que
chamamos de triplo de driver.
A Estrutura, que manipula tarefas comuns à maioria dos drivers
A extensão de estrutura baseada em classe, que lida com tarefas específicas de
uma classe específica de dispositivos
O driver KMDF, que manipula tarefas específicas de um dispositivo específico.
Os três drivers em um driver triplo (driver KMDF, extensão KMDF da classe de
dispositivo, Framework) combinam para formar um único driver WDM.
Um exemplo de uma extensão KMDF da classe de dispositivo é [Link], que é a
extensão KMDF para a classe de dispositivo SPB (Barramento Periférico Simples). A
classe SPB inclui barramentos serial síncronos, como I2C e SPI. Um driver triplo para um
controlador de barramento I2C teria esta aparência:
A Estrutura lida com tarefas gerais que são comuns à maioria dos drivers.
[Link] lida com tarefas específicas da classe de barramento SPB. Essas são
tarefas comuns a todos os barramentos SPB.
O driver KMDF lida com tarefas específicas de um barramento I2C. Vamos chamar
esse driver de [Link].
Os três drivers no driver triplo ([Link], [Link] [Link]) combinam
para formar um único driver WDM que serve como o driver de função para o
controlador de barramento I2C. [Link] (o Framework) possui a tabela de
expedição para esse driver, portanto, quando alguém envia um IRP para o driver triplo,
ele vai para o [Link]. Se o [Link] puder lidar com o IRP por si só,
[Link] e [Link] não estarão envolvidos. Se [Link] não puder
lidar com o IRP sozinho, ele receberá ajuda chamando um manipulador de eventos no
[Link].
Aqui estão alguns exemplos de manipuladores de eventos que podem ser
implementados por [Link]:
EvtSpbControllerLock
EvtSpbIoRead
EvtSpbIoSequence
Aqui estão alguns exemplos de manipuladores de eventos implementados pelo
[Link]
EvtIoRead
Comentários
Esta página foi útil? Yes No
Fornecer comentários sobre o produto | Obter ajuda no Microsoft Q&A
Bordas superiores e inferiores dos
drivers
Artigo • 15/06/2023
A sequência de drivers que participam de uma solicitação de E/S é chamada de pilha de
driver para a solicitação. Um driver pode chamar na borda superior de um driver inferior
na pilha. Um driver também pode chamar a borda inferior de um driver mais alto na
pilha.
Antes de ler este tópico, você deve entender as ideias apresentadas em Nós de
dispositivo e pilhas de dispositivos e pilhas de driver.
As solicitações de E/S são processadas primeiro pelo driver superior na pilha de driver,
depois pelo próximo driver inferior e assim por diante até que a solicitação seja
totalmente processada.
Quando um driver implementa um conjunto de funções que um driver superior pode
chamar, esse conjunto de funções é chamado de borda superior do driver ou a interface
de borda superior do driver.
Quando um driver implementa um conjunto de funções que um driver inferior pode
chamar, esse conjunto de funções é chamado de borda inferior do driver ou a interface
de borda inferior do driver.
Exemplo de áudio
Podemos pensar em um driver de miniporta de áudio sentado abaixo de um driver de
porta de áudio em uma pilha de driver. O driver de porta faz chamadas para a borda
superior do driver de miniporta. O driver de miniporta faz chamadas para a borda
inferior do driver de porta.
O diagrama anterior ilustra que às vezes é útil pensar em um driver de porta sentado
acima de um driver de miniporta em uma pilha de driver. Como as solicitações de E/S
são processadas primeiro pelo driver de porta e, em seguida, pelo driver de miniporta, é
razoável pensar no driver de porta como sendo acima do driver de miniporta. Tenha em
mente, no entanto, que um par de drivers (miniport, porta) geralmente fica em um
único nível em uma pilha de dispositivos, conforme mostrado aqui.
Observe que uma pilha de dispositivos não é a mesma coisa que uma pilha de driver.
Para obter definições desses termos e para uma discussão sobre como um par de
drivers pode formar um único driver WDM que ocupa um nível em uma pilha de
dispositivos, consulte Minidrivers e pares de drivers.
Aqui está outra maneira de desenhar um diagrama do mesmo nó de dispositivo e pilha
de dispositivos:
No diagrama anterior, vemos que o par (miniport, porta) forma um único driver WDM
associado a um único objeto de dispositivo (o FDO) na pilha do dispositivo; ou seja, o
par (miniport, porta) ocupa apenas um nível na pilha do dispositivo. Mas também
vemos uma relação vertical entre os drivers de miniporta e porta. O driver de porta é
mostrado acima do driver de miniporto para indicar que o driver de porta processa
solicitações de E/S primeiro e, em seguida, chama o driver de miniporto para
processamento adicional.
O ponto chave é que, quando o driver de porta chama a interface de borda superior do
driver de miniport, isso não é o mesmo que passar uma solicitação de E/S para baixo na
pilha do dispositivo. Em uma pilha de driver (não na pilha de dispositivos), você pode
optar por desenhar um driver de porta acima de um driver de miniporta, mas isso não
significa que o driver de porta esteja acima do driver de miniporta na pilha do
dispositivo.
Exemplo de NDIS
Às vezes, um driver chama a borda superior de um driver inferior indiretamente. Por
exemplo, suponha que um driver de protocolo TCP/IP esteja acima de um driver de
miniporta NDIS em uma pilha de driver. O driver de miniporta implementa um conjunto
de funções MiniportXxx que formam a borda superior do driver de miniporto. Dizemos
que o driver de protocolo TCP/IP é associado à borda superior do driver de miniporto
NDIS. Mas o driver TCP/IP não chama as funções MiniportXxx diretamente. Em vez disso,
ele chama funções na biblioteca NDIS, que, em seguida, chamam as funções
MiniportXxx .
O diagrama anterior mostra uma pilha de driver. Aqui está outra visão dos mesmos
drivers.
O diagrama anterior mostra o nó do dispositivo para uma NIC (cartão de interface de
rede). O nó do dispositivo tem uma posição na árvore de dispositivos Plug and Play
(PnP). O nó do dispositivo para a NIC tem uma pilha de dispositivos com três objetos de
dispositivo. Observe que o driver de miniporto NDIS e a biblioteca NDIS funcionam
como um par. O par ([Link], [Link]) forma um único driver WDM
representado pelo FDO (objeto de dispositivo funcional).
Observe também que o driver de protocolo [Link] não faz parte da pilha do
dispositivo para a NIC. Na verdade, [Link] não faz parte da árvore de dispositivos
PnP.
Resumo
Os termos borda superior e borda inferior são usados para descrever as interfaces que os
drivers em uma pilha usam para se comunicar entre si. Uma pilha de driver não é a
mesma coisa que a pilha de dispositivos. Dois drivers mostrados verticalmente em uma
pilha de driver podem formar um par de drivers que fica em um único nível em uma
pilha de dispositivos. Alguns drivers não fazem parte da árvore de dispositivos PnP.
Tópicos relacionados
Conceitos para todos os desenvolvedores de driver
Nós de dispositivo e pilhas de dispositivos
Pilhas de driver
Dispositivos de áudio
Drivers de rede começando com o Windows Vista
Comentários
Esta página foi útil? Yes No
Fornecer comentários sobre o produto | Obter ajuda no Microsoft Q&A
Arquivos de cabeçalho no Kit de Driver
do Windows
Artigo • 30/12/2024
Os documentos de referência da API para o WDK (Windows Driver Kit) contém todos os
arquivos de cabeçalho (arquivos.h) necessários para criar drivers no modo kernel e no
modo de usuário. Os arquivos de cabeçalho estão na pasta Incluir na pasta de instalação
do WDK. Exemplo: C:\Arquivos de Programas (x86)\Kits do Windows\10\Include.
Os arquivos de cabeçalho contêm informações de versão para que você possa usar o
mesmo conjunto de arquivos de cabeçalho, independentemente de qual versão do
Windows seu driver será executado.
Constantes que representam versões do
Windows
Os arquivos de cabeçalho no WDK contêm instruções condicionais que especificam
elementos de programação disponíveis apenas em determinadas versões do sistema
operacional Windows. Os elementos com versão incluem funções, enumerações,
estruturas e membros da estrutura.
Para especificar os elementos de programação disponíveis em cada versão do sistema
operacional, os arquivos de cabeçalho contêm condicionais de pré-processador que
comparam o valor de NTDDI_VERSION com um conjunto de valores constantes
predefinidos definidos em Sdkddkver.h.
Aqui estão os valores de constante predefinidos que representam versões do sistema
operacional Microsoft Windows.
ノ Expandir a tabela
Constante Versão do sistema operacional
NTDDI_WIN10 Windows 10
NTDDI_WINBLUE Windows 8.1
NTDDI_WIN8 Windows 8
NTDDI_WIN7 Windows 7
NTDDI_WS08SP4 Windows Server 2008 com SP4
Constante Versão do sistema operacional
NTDDI_WS08SP3 Windows Server 2008 com SP3
NTDDI_WS08SP2 Windows Server 2008 com SP2
NTDDI_WS08 Windows Server 2008
Você pode ver muitos exemplos de elementos DDI específicos à versão nos arquivos de
cabeçalho do WDK. Essa declaração condicional é exibida no Wdm.h, que é um arquivo
de cabeçalho que pode ser incluído por um driver no modo kernel.
C++
#if (NTDDI_VERSION >= NTDDI_WIN7)
_Must_inspect_result_
NTKERNELAPI
NTSTATUS
KeSetTargetProcessorDpcEx (
_Inout_ PKDPC Dpc,
_In_ PPROCESSOR_NUMBER ProcNumber
);
#endif
No exemplo, você pode ver que a função KeSetTargetProcessorDpcEx está disponível
apenas no Windows 7 e versões posteriores do Windows.
Essa declaração condicional aparece no Winspool.h, que é um arquivo de cabeçalho que
pode ser incluído por um driver de modo de usuário.
ManagedCPlusPlus
#if (NTDDI_VERSION >= NTDDI_WIN7)
...
BOOL
WINAPI
GetPrintExecutionData(
_Out_ PRINT_EXECUTION_DATA *pData
);
#endif // (NTDDI_VERSION >= NTDDI_WIN7)
No exemplo, é possível ver que a função GetPrintExecutionData está disponível apenas
no Windows 7 e versões posteriores do Windows.
Arquivos de cabeçalho para a Estrutura de
driver do modo kernel
O WDK dá suporte a várias versões do Windows e também dá suporte a várias versões
do KMDF (Kernel Mode Driver Framework) e do UMDF (User Mode Driver Framework).
As informações de controle de versão nos arquivos de cabeçalho do WDK pertencem às
versões do Windows, mas não às versões KMDF ou UMDF. Arquivos de cabeçalho para
versões diferentes de KMDF e UMDF são colocados em diretórios separados.
Comentários
Esta página foi útil? Yes No
Fornecer comentários sobre o produto | Obter ajuda no Microsoft Q&A
Escrevendo drivers para diferentes
versões do Windows
Artigo • 20/03/2024
Ao criar um projeto de driver, você especifica o sistema operacional de destino mínimo,
que é a versão mínima do Windows na qual o driver será executado. Por exemplo, você
pode especificar que o Windows 7 é o sistema operacional de destino mínimo. Nesse
caso, o driver seria executado no Windows 7 e versões posteriores do Windows.
7 Observação
Se você desenvolver um driver para uma versão mínima específica do Windows e
quiser que o driver funcione em versões posteriores do Windows, não deverá usar
nenhuma função não documentada e não deverá usar funções documentadas de
outra forma que não seja a descrita na documentação. Caso contrário, o driver
pode falhar ao ser executado nas versões posteriores do Windows. Mesmo se você
tiver tido o cuidado de usar apenas funções documentadas, você deve testar seu
driver na nova versão do Windows cada vez que um é lançado.
Escrevendo um driver de várias versões usando
apenas recursos comuns
Quando você cria um driver que será executado em várias versões do Windows, a
abordagem mais simples é permitir que o driver use apenas funções DDI e estruturas
que são comuns a todas as versões do Windows em que o driver será executado. Nessa
situação, você define o sistema operacional de destino mínimo para a versão mais
antiga do Windows que o driver suportará.
Por exemplo, para oferecer suporte a todas as versões do Windows, começando com o
Windows 7, você deve:
1. Projete e implemente o driver para que ele use apenas os recursos que estão
presentes no Windows 7.
2. Ao criar o driver, especifique o Windows 7 como o sistema operacional de destino
mínimo.
Embora esse processo seja simples, ele pode restringir o driver a usar apenas um
subconjunto da funcionalidade que está disponível em versões posteriores do Windows.
Em muitos casos, convém fazer uso da funcionalidade mais recente do sistema
operacional quando ela estiver disponível para melhorar a segurança, melhorar a
confiabilidade ou habilitar recursos mais recentes.
Escrevendo um driver de várias versões que usa
recursos dependentes da versão
Um driver de modo kernel pode determinar dinamicamente se uma API fornecida pelo
sistema operacional está disponível ou em qual versão do Windows o driver está sendo
executado e optar por usar os recursos disponíveis nesse ambiente de tempo de
execução. Por exemplo, um driver que deve oferecer suporte a todas as versões do
Windows, começando com o Windows 7, pode determinar, em tempo de execução, a
versão do Windows em que ele está sendo executado. Se o driver estiver sendo
executado no Windows 7, ele deve usar apenas as funções DDI que o Windows 7
suporta. No entanto, o mesmo driver pode usar funções DDI adicionais que são
exclusivas do Windows 8, por exemplo, quando sua verificação de tempo de execução
determina que essas APIs estão presentes no momento ou determina que ele está
sendo executado no Windows 8.
7 Observação
É recomendável que você verifique a disponibilidade de recursos ou API sempre
que possível, em vez de tentar verificar se o driver está sendo executado em uma
determinada versão do sistema operacional ou posterior.
Chamando condicionalmente funções dependentes da
versão do Windows
Um driver de modo kernel pode usar as funções MmGetSystemRoutineAddress ou
MmGetSystemRoutineAddressEx para verificar dinamicamente se uma API específica
que deseja usar está disponível no ambiente de tempo de execução atual e para obter
um ponteiro de função a ser usado para chamar essa API.
7 Observação
Para ajudar a preservar a verificação de tipo e evitar erros não intencionais, você
deve criar um typedef que espelhe o tipo de função original.
Exemplo: Determinando a disponibilidade da API e chamando
condicionalmente a API
C++
typedef
NTSTATUS
(*PFN_IoOpenDriverRegistryKey)(
PDRIVER_OBJECT DriverObject,
DRIVER_REGKEY_TYPE RegKeyType,
ACCESS_MASK DesiredAccess,
ULONG Flags,
PHANDLE DriverRegKey
);
VOID ExampleFunction(VOID) {
NTSTATUS status = STATUS_UNSUCCESSFUL;
HANDLE persistentStateKey = NULL;
PFN_IoOpenDriverRegistryKey pfnIoOpenDriverRegistryKey = NULL;
UNICODE_STRING functionName = {0};
RtlInitUnicodeString(&functionName, L"IoOpenDriverRegistryKey");
pfnIoOpenDriverRegistryKey =
(PFN_IoOpenDriverRegistryKey)MmGetSystemRoutineAddress(&functionName);
if (pfnIoOpenDriverRegistryKey != NULL) {
// Open a key to where state can be stored under the driver service
status = pfnIoOpenDriverRegistryKey(g_GlobalStructure.DriverObject,
DriverRegKeyPersistentState,
KEY_WRITE,
0,
&persistentStateKey);
} else {
// Fall back to opening up a different location to store state in
}
// Use the opened registry key
}
Determinando a versão do Windows
Um driver de modo kernel pode usar a função RtlVerifyVersionInfo para verificar
dinamicamente em qual versão do Windows ele está sendo executado no momento.
7 Observação
É recomendável que você verifique a disponibilidade de recursos ou API sempre
que possível, em vez de tentar verificar se o driver está sendo executado em uma
determinada versão do sistema operacional ou posterior.
Exemplo: Determinando a versão do Windows
O exemplo a seguir detecta se a versão do sistema operacional em execução no
momento é maior ou igual à versão 10.0 e detecta se o número de compilação é maior
ou igual à compilação 22000 (Windows 11, versão 21H2).
C++
...
NTSTATUS Status = STATUS_SUCCESS;
RTL_OSVERSIONINFOEXW VersionInfo = {0};
ULONG TypeMask = 0;
ULONGLONG ConditionMask = 0;
[Link] = sizeof(VersionInfo);
[Link] = 10;
[Link] = 0;
[Link] = 22000;
TypeMask = VER_MAJORVERSION | VER_MINORVERSION | VER_BUILDNUMBER;
VER_SET_CONDITION(ConditionMask, VER_MAJORVERSION, VER_GREATER_EQUAL);
VER_SET_CONDITION(ConditionMask, VER_MINORVERSION, VER_GREATER_EQUAL);
VER_SET_CONDITION(ConditionMask, VER_BUILDNUMBER, VER_GREATER_EQUAL);
Status = RtlVerifyVersionInfo(&VersionInfo,
TypeMask,
ConditionMask);
if (NT_SUCCESS(Status)) {
//
// The call to RtlVerifyVersionInfo succeeded, so the running OS
// version and build number is greater than or equal to the value
// specified. Do appropriate action for newer OS versions.
//
} else if (Status == STATUS_REVISION_MISMATCH) {
//
// The running OS version is less than the value specified. Do
// appropriate action for older OS versions.
//
} else {
//
// There was an error comparing to the running OS version. Do
// appropriate action for when the OS version is not known.
//
}
...
Comentários
Esta página foi útil? Yes No
Fornecer comentários sobre o produto | Obter ajuda no Microsoft Q&A