INFO: Dicas para o Windows NT driver desenvolvedores--que é importante evitar

Traduções deste artigo Traduções deste artigo
ID do artigo: 186775 - Exibir os produtos aos quais esse artigo se aplica.
Expandir tudo | Recolher tudo

Sumário

Seguem algumas dicas para criar drivers de dispositivo do Windows NT. As dicas apresentadas se aplicam a todas as tecnologias. Você também pode usar isso como uma lista de verificação para solucionar problemas de driver.

Você precisa ter um conhecimento básico da arquitetura do Windows NT e alguns desenvolvimento de driver de dispositivo experiência usar as informações apresentadas abaixo com eficiência. Para obter mais informações sobre desenvolvimento de driver de dispositivo, consulte o kit de driver de dispositivo de Windows NT (DDK), que está disponível através de participação em MSDN Professional.

Mais Informações

A seguir está uma lista de coisas que os desenvolvedores devem evitar ao trabalhar com drivers de dispositivo do Windows NT:

  1. Nunca retorno STATUS_PENDING de uma rotina de expedição sem marcar o pacote de solicitação de E/s (IRP) pendente (IoMarkIrpPending).
  2. Nunca chamar KeSynchronizeExecution a partir de uma rotina de serviço de interrupção (ISR). Ele será deadlock seu sistema.
  3. Nunca defina DeviceObject-> sinalizadores como tanto DO_BUFFERED_IO DO_DIRECT_IO. Ele pode confundir o sistema e, eventualmente, levar a erro fatal. Além disso, nunca defina METHOD_BUFFERED, METHOD_NEITHER, METHOD_IN_DIRECT ou METHOD_OUT_DIRECT em DeviceObject-> sinalizadores, porque esses valores são usados apenas definindo IOCTLs.
  4. Nunca aloca objetos dispatcher de um pool paginável. Se você fizer isso, isso causará bugchecks sistema ocasional.
  5. Nunca alocar memória de pool paginada ou acesso a memória do pool paginável, durante a execução em um IRQL > = DISPATCH_LEVEL. É um erro fatal.
  6. Nunca esperar por um objeto dispatcher de kernel para um intervalo diferente de zero em um IRQL > = DISPATCH_LEVEL. É um erro fatal.
  7. Nunca chamada qualquer função que faz com que o thread de chamada para aguardar direta ou indiretamente durante a execução em um IRQL > = DISPATCH_LEVEL. É um erro fatal.
  8. Nunca diminua o nível de solicitação de interrupção (IRQL) abaixo do nível em que sua rotina de nível superior foi invocada.
  9. Nunca chame KeLowerIrql() se você ainda não chamado KeRaiseIrql().
  10. Nunca vaga um processador (KeStallExecutionProcessor) mais de 50 microssegundos.
  11. Nunca mantenha os bloqueios de rotação mais necessário. Para melhor desempenho geral do sistema, não segure qualquer bloqueios de rotação de todo o sistema mais de 25 microssegundos.
  12. Nunca chama KeAcquireSpinLock e KeReleaseSpinLock, ou KeAcquireSpinLockAtDpcLevel e KeReleaseSpinLockFromDpcLevel, durante a execução em um IRQL maior DISPATCH_LEVEL.
  13. Nunca Libere um bloqueio de rotação que foi adquirido com KeAcquireSpinLock pela chamada KeReleaseSpinLockFromDpcLevel, porque o IRQL original não será restaurado.
  14. Nunca chame KeAcquireSpinLock e KeReleaseSpinLock ou qualquer rotina que usa um bloqueio de rotação executivo de um routine(s) ISR ou SynchCritSection.
  15. Jamais se esqueça de Limpar sinalizador DO_DEVICE_INITIALIZING quando você cria um objeto de dispositivo em uma rotina seja DriverEntry.
  16. Nunca fila um objeto de chamada (DPC) de procedimento deferidas (usando KeInsertQueueDpc) com vários threads em diferentes processadores, simultaneamente. Ele pode levar a erro fatal.
  17. Nunca desalocar um timer periódico de uma rotina CutomerTimerDPC. Você pode desalocar nonperiodic timers de uma rotina DPC.
  18. Nunca passar o ponteiro DPC mesmo para KeSetTimer ou KeSetTimerEx (CustomTimerDpc) e KeInsertQueueDpc (CustomDpc), porque ela faz com que as condições de corrida.
  19. Chamada de nunca IoStartNextPacket mantendo um bloqueio de rotação. Ele pode deadlock seu sistema.
  20. Chamada de nunca IoCompleteRequest mantendo um bloqueio de rotação. Ele pode deadlock seu sistema.
  21. Nunca chame IoCompleteRequest sem definir a rotina de conclusão para NULL se o driver define a rotina de conclusão.
  22. Jamais se esqueça de definir o bloco de status de E/s no IRP antes de chamar IoCompleteRequest.
  23. Nunca chame IoMarkPending após enfileiramento um IRP ou enviá-lo para outro driver (IoCallDriver). O IRP pode ser concluído antes que o driver chama IoMarkPending e após uma verificação de erro pode ocorrer. Para drivers com rotinas de conclusão, as rotinas de conclusão devem chamar IoMarkPending se IRP-> PendingReturned estiver definida.
  24. Toca um IRP nunca após você ter chamado IoCompleteRequest nele.
  25. Nunca chame IoCancelIrp em um IRP que não pertence a seu driver a menos que saiba que o IRP ainda não foi concluído.
  26. Nunca chame IoCancelIrp para o IRP sua rotina de expedição está trabalhando em até que sua rotina de expedição retorna ao chamador.
  27. Nunca chame IoMakeAssociatedIrp Criar IRPs para drivers inferiores de um driver intermediário. O IRP que você obtém seu driver intermediário poderia ser um IRP associado e não é possível associar outros IRPs para um IRP já associado.
  28. Nunca chamada IoMakeAssociatedIrp em um IRP que está configurado para realizar buffer de E/s.
  29. Nunca simplesmente eliminar referência virtuais ponteiros para registradores de E/s de dispositivo e acessá-los. Sempre use funções de camada de abstração de hardware (HAL) de abstração de hardware correto para acessar um dispositivo.
  30. Nunca acesso IRP ou dispositivo campos de objeto de um ISR pode ser modificado de DISPATCH_LEVEL. Em um sistema multiprocessador simétrico isso pode causar corrupção de dados.
  31. Nunca modifique dados durante a execução em um IRQL alto se os dados podem ser escritos por código de IRQL baixa. Use a rotina KeSynchronizeExecution.
  32. Nunca adquira um dos bloqueios de rotação do driver (se houver) em sua rotina DispatchCleanup, antes de adquirir o bloqueio de rotação cancelar todo o sistema (IoAcquireCancelSpinLock). Após uma hierarquia de aquisição de bloqueio consistente em todo o driver é essencial para evitar deadlocks potenciais.
  33. Nunca chamada IoAcquireCancelSpinLock em sua rotina de cancelamento porque sempre é chamado com o sistema de bloqueio de rotação Cancelar mantido em seu nome.
  34. Jamais se esqueça de chamar IoReleaseCancelSpinLock antes de retornar de uma rotina de cancelamento.
  35. Nunca use sincronização baseado em IRQL como isso funciona somente em sistemas de único processador. Aumentando a IRQL em um processador máscara não interrupções em outros processadores.
  36. Nunca use RtlCopyMemory para intervalos de endereço de memória sobreposta. Uso RtlMoveMemory.
  37. Nunca suponha tamanhos de página são constantes, mesmo para uma determinada CPU. Uso PAGE_SIZE e outra página relacionados constantes definidas nos arquivos de cabeçalho para manter a portabilidade.
  38. Nunca acessar quaisquer chaves do Registro sejam Registry\Machine\Hardware e Registry\Machine\System de rotina DriverEntry de um driver carregado na fase de inicialização Boot\System.
  39. Nunca crie uma chave Enum para carregar um driver de chave de registro do driver (Registry\Machine\System\CurrentControlSet\Services). O sistema cria esta chave dinamicamente.
  40. Nunca tentativa para inicializar um dispositivo físico sem declarar o portas de E/s necessárias relativo de barramento, intervalos de memória, interrupção ou acesso direto à memória (DMA) canal/porta recursos de hardware no registro pela primeira vez.
  41. Nunca chamar IoRegisterDriverReinitialization a partir do seu DriverEntry rotina, a menos que ele retornará STATUS_SUCCESS.
  42. Nunca chame KeSetEvent com o conjunto de parâmetro de espera para TRUE de um thread paginável ou rotina paginável driver que é executado no IRQL PASSIVE_LEVEL. Este tipo de chamada faz com que uma falha de página fatal caso sua rotina seja paginada a saída entre as chamadas para KeSetEvent e KeWaitObjeto (s).
  43. Nunca chame KeReleaseSemaphore com o conjunto de parâmetro de espera para TRUE de um thread paginável ou rotina paginável driver que é executado no IRQL PASSIVE_LEVEL. Caso sua rotina seja paginada a saída entre as chamadas para KeReleaseSemaphore e KeWaitObjeto (s) Este tipo de uma chamada faz com que uma falha de página fatal.
  44. Nunca chame KeReleaseMutex com o conjunto de parâmetro de espera para TRUE de um thread paginável ou rotina paginável driver que é executado no IRQL PASSIVE_LEVEL. Caso sua rotina seja paginada a saída entre as chamadas para KeReleaseMutex e KeWaitObjeto (s) Este tipo de uma chamada faz com que uma falha de página fatal.
  45. Nunca chamar KeBugCheckEx ou KeBugCheck a partir de um driver de varejo do Windows NT para trazer o sistema, a menos que o erro é um erro crítico que poderia danificar a memória do sistema ou eventualmente causar a verificação de erro do sistema. Sempre tente manipular condições de erro normalmente.
  46. Nunca suponha que uma rotina de IoTimer será chamada com precisão em um limite de um segundo porque os intervalos no qual qualquer IoTimer específico é chamada de rotina depende resolução do relógio do sistema.
  47. Nunca chamar interfaces Win32s de programação de aplicativo (API) de um driver de dispositivo de modo kernel.
  48. Nunca use recursiva funções que podem causar a pilha do estouro porque a chamada pilha do thread de modo kernel não aumentar dinamicamente enquanto ele estiver sendo executado no modo de kernel.
  49. Nunca use ponteiros de objeto de interrupção (PKINTERRUPT) que lida com mais de uma interrupção, para identificar as interrupções em um ISR porque o endereço do objeto interrupção que você obtém o ISR não sempre serão o mesmo que você obteve do IoConnectInterrupt. Você deve usar somente o valor de ServiceContext que você especificar na IoConnectInterrupt para identificar o dispositivo de interrupção atual.
  50. Nunca descarrega um driver sem limpar CustomTimerDpc (KeCancelTimer). Se o DPC é acionado depois que o driver é descarregado, ele foi atingido existente não-código e fazer com que o sistema verificação de defeito.
  51. Nunca descarregar um driver até que todos os IRPs que têm o CompletionRoutine de E/s do driver definido nele são concluídas. Se o IRP obtém completado pelo driver inferior depois que o driver é descarregado, o sistema pode tentar executar o código não-existente e fazer com que o sistema falha.
  52. Nunca ative interrupção de dispositivo até que o driver esteja pronto para manipulá-lo. Você deve habilitar somente depois que o driver é inicializado completamente e é seguro para o sistema tocar estruturas internas do driver em DPC e ISR.
  53. Nunca chamada fora de seu driver mantendo um spinlock porque pode causar bloqueio.
  54. Nunca retorno qualquer status diferente de STATUS_MORE_PROCESSING_REQUIRED de seu CompletionRoutine de E/s para um IRP criado pelo seu driver com IoBuildAsynchronousFsdRequest/IoAllocateIrp porque o IRP não está preparado para conclusão relacionadas pós-processamento pelo Gerenciador de E/s. Como um IRP deve ser liberado explicitamente (IoFreeIrp) pelo driver. Se o IRP não serve para reutilização, pode ser liberado na CompletionRoutine antes de retornar status STATUS_MORE_PROCESSING_REQUIRED.
  55. Nunca alocar um IRP com IoBuildSynchronousFsdRequest/IoBuildDeviceIoControlRequest em um contexto de segmento arbitrário porque o IRP permanecerá associado ao thread (IRP-> ThreadListEntry) até que ele seja liberado.
  56. Nunca chame IoInitializeIrp em um IRP que foi alocado com IoAllocateIrp com ChargeQuota parâmetro definido como TRUE. Quando você alocar um IRP com ChargeQuota definido como TRUE, o gerente de E/s mantém as informações sobre o pool do qual ele a memória alocada para o IRP em sinalizador interno do IRP.

    Quando você chama IoInitializeIrp no como um IRP, as informações de pool de alocação serão perdidas como essa função zeros cegamente o IRP inteiro. Isso leva à corrupção de memória quando você liberar o IRP. Além disso, nunca reutilize um IRP que vem do Gerenciador de E/S. Se desejar reutilizar um IRP, você deve alocar seu próprio usando IoAllocateIrp.
  57. Especifica nunca WaitMode como UserMode em KeWaitForSingleObject/KeWaitForMultipleObjects se o objeto é alocado na pilha do thread de chamada. O resultado disso é que se o objeto sendo aguardado for criado na pilha de função, você precisa especificar KernelMode como WaitMode para impedir que a pilha de thread sendo paginada fora.
  58. Nunca adquira recursos como ERESOURCES e FastMutex(Unsafe) no contexto de um segmento de modo de usuário sem proteger o código em uma seção crítica.

    Como a aquisição desses recursos não aumenta o IRQL para APC_LEVEL, se o thread é suspensa (feito pelo enfileiramento um APC) depois que ele tiver adquirido o recurso, ele pode causar bloqueio e comprometimento da segurança do sistema. Portanto, você deve adquirir esses recursos o levantando explicitamente o IRQL APC_LEVEL ou em uma seção crítica chamando KeEnterCriticalRegion.

Referências

Guia de design de driver de dispositivo do MSDN para o Windows NT

Propriedades

ID do artigo: 186775 - Última revisão: terça-feira, 27 de julho de 2004 - Revisão: 2.1
A informação contida neste artigo aplica-se a:
  • Microsoft Win32 Device Driver Kit for Windows NT 3.51
  • Microsoft Win32 Device Driver Kit for Windows NT 4.0
Palavras-chave: 
kbmt kbinfo KB186775 KbMtpt
Tradução automática
IMPORTANTE: Este artigo foi traduzido por um sistema de tradução automática (também designado por Machine Translation ou MT), não tendo sido portanto traduzido ou revisto por pessoas. A Microsoft possui artigos traduzidos por aplicações (MT) e artigos traduzidos por tradutores profissionais, com o objetivo de oferecer em português a totalidade dos artigos existentes na base de dados de suporte. No entanto, a tradução automática não é sempre perfeita, podendo conter erros de vocabulário, sintaxe ou gramática. A Microsoft não é responsável por incoerências, erros ou prejuízos ocorridos em decorrência da utilização dos artigos MT por parte dos nossos clientes. A Microsoft realiza atualizações freqüentes ao software de tradução automática (MT). Obrigado.
Clique aqui para ver a versão em Inglês deste artigo: 186775
Aviso de Isenção de Responsabilidade sobre Conteúdo do KB Aposentado
Este artigo trata de produtos para os quais a Microsoft não mais oferece suporte. Por esta razão, este artigo é oferecido "como está" e não será mais atualizado.

Submeter comentários

 

Contact us for more help

Contact us for more help
Connect with Answer Desk for expert help.
Get more support from smallbusiness.support.microsoft.com