INFO: Sugestões para o Windows NT Driver programadores--itens para evitar

Traduções de Artigos Traduções de Artigos
Artigo: 186775 - Ver produtos para os quais este artigo se aplica.
Expandir tudo | Reduzir tudo

Sumário

Seguem-se alguns sugestões para criar controladores de dispositivo do Windows NT. As sugestões apresentadas se aplicam a todas as tecnologias. Também pode utilizar isto como uma lista de verificação para resolver problemas de controlador.

Tem de ter um conhecimento básico de arquitectura do Windows NT e algumas desenvolvimento de controlador de dispositivo experimentar utilizar as informações apresentadas abaixo eficazmente. Para mais informações sobre o desenvolvimento de controladores de dispositivo, consulte o kit de controlador do dispositivo Windows NT (DDK), que está disponível através da associação Professional da MSDN.

Mais Informação

Segue-se uma lista de coisas que os programadores devem evitar quando trabalhar com controladores de dispositivo do Windows NT:

  1. Nunca devolução STATUS_PENDING a partir de uma rotina de despacho sem marcar o pacote de pedido de E/s (IRP) pendente (IoMarkIrpPending).
  2. Nunca chamar KeSynchronizeExecution a partir de uma rotina do serviço de interrupção (ISR). -Criar um impasse do sistema.
  3. Defina nunca DeviceObject-> sinalizadores para tanto DO_BUFFERED_IO DO_DIRECT_IO. Pode confundir o sistema e eventualmente conduzir a erro fatal. Além disso, nunca estabelecer METHOD_BUFFERED, METHOD_NEITHER, METHOD_IN_DIRECT ou METHOD_OUT_DIRECT no DeviceObject-> sinalizadores, porque estes valores são utilizados apenas na definição IOCTLs.
  4. Atribuir nunca despachante de objectos a partir de um bloco paginado. Se o fizer, causará bugchecks sistema ocasional.
  5. Nunca atribuir memória a partir de bloco paginado ou aceder a memória de bloco paginado, durante a execução no IRQL > = DISPATCH_LEVEL. Trata-se um erro fatal.
  6. Nunca aguardar num objecto kernel despachante de um intervalo diferente de zero no IRQL > = DISPATCH_LEVEL. Trata-se um erro fatal.
  7. Nunca chamada qualquer função que faz com que o thread de chamada aguardar directa ou indirectamente durante a execução no IRQL > = DISPATCH_LEVEL. Trata-se um erro fatal.
  8. Nunca diminuir o nível de pedido de interrupção (IRQL) abaixo do nível que a rotina de nível superior foi invocou.
  9. Chamar KeLowerIrql() nunca se ainda não chamado KeRaiseIrql().
  10. Nunca lugar um processador (KeStallExecutionProcessor) mais de 50 microssegundos.
  11. Nunca conter quaisquer bloqueios de rotação mais do que necessário. Para melhor desempenho global do sistema, não conter quaisquer bloqueios de rotação de todo o sistema mais de 25 microssegundos.
  12. Chamar nunca KeAcquireSpinLock KeReleaseSpinLock, ou KeAcquireSpinLockAtDpcLevel e KeReleaseSpinLockFromDpcLevel, durante a execução no IRQL superior DISPATCH_LEVEL.
  13. Nunca Liberte um bloqueio de rotação foi adquirido com KeAcquireSpinLock por KeReleaseSpinLockFromDpcLevel chamada, porque o IRQL original não será restaurado.
  14. Nunca chame KeAcquireSpinLock e KeReleaseSpinLock ou qualquer outra rotina que utiliza um bloqueio de rotação executivo a partir de um routine(s) ISR ou SynchCritSection.
  15. Nunca esquecer de Limpar sinalizador DO_DEVICE_INITIALIZING quando cria um objecto de dispositivo numa rotina seja DriverEntry.
  16. Fila nunca um objecto de chamada (DPC) de procedimentos adiadas (utilizando KeInsertQueueDpc) com vários threads em diferentes processadores simultaneamente. Pode levar a erro fatal.
  17. Nunca deallocate um temporizador periódico a partir de uma rotina CutomerTimerDPC. Pode retirar a atribuição nonperiodic temporizadores a partir de uma rotina DPC.
  18. Nunca passar o ponteiro DPC mesmo para KeSetTimer ou KeSetTimerEx (CustomTimerDpc) e KeInsertQueueDpc (CustomDpc), uma vez que faz com que Pilote condições.
  19. Nunca chamada IoStartNextPacket mantendo um bloqueio de rotação. -Pode criar um impasse do sistema.
  20. Nunca chamada IoCompleteRequest mantendo um bloqueio de rotação. -Pode criar um impasse do sistema.
  21. Nunca chame IoCompleteRequest sem definir a rotina de conclusão para NULL se o controlador define a conclusão da rotina.
  22. Nunca esquecer-se definir o bloco de estado de E/s de IRP antes de chamar IoCompleteRequest.
  23. Nunca chame IoMarkPending depois de colocar em fila um IRP ou enviar para outro controlador (IoCallDriver). O IRP poderá ser concluído antes do controlador de chamadas IoMarkPending e poderá ocorrer uma verificação de defeito. Para controladores com rotinas de conclusão, as rotinas de conclusão tem de chamar IoMarkPending se Irp-> PendingReturned estiver definido.
  24. Toca um IRP nunca depois de ter chamado IoCompleteRequest nele.
  25. Nunca chamar IoCancelIrp num IRP não pertence ao controlador a menos que saiba que o IRP ainda não foi concluído.
  26. Nunca chamar IoCancelIrp para o IRP a rotina de distribuição está a trabalhar quando a rotina de despacho regressa ao autor da chamada.
  27. Nunca chame IoMakeAssociatedIrp Criar IRPs para controladores inferiores de um controlador intermédio. IRP que obtém no seu controlador intermédio pode ser um IRP associado e não é possível associar outros IRPs para um IRP já associada.
  28. Nunca chamada IoMakeAssociatedIrp num IRP que está configurado para efectuar armazenada em buffer E/s.
  29. Nunca basta anular a referência de apontadores virtuais para registos de E/s de dispositivo e aceder aos mesmos. Utilize sempre funções de camada de abstracção de hardware (HAL) de abstracção de hardware correcta para aceder a um dispositivo.
  30. Nunca aceder IRP ou dispositivo de campos de objecto a partir de um ISR que pode ser modificado de DISPATCH_LEVEL. Num sistema multiprocessador simétrico Isto pode causar danos nos dados.
  31. Nunca modificar dados durante a execução no IRQL alta se os dados podem ser escritos por código de IRQL baixa. Utilize a rotina KeSynchronizeExecution.
  32. Nunca Adquira um os bloqueios de rotação do controlador (se tiver um) na sua rotina DispatchCleanup, antes de adquirir o bloqueio de rotação de todo o sistema Cancelar (IoAcquireCancelSpinLock). Após uma hierarquia de aquisição de bloqueio consistente em todo o controlador é essencial para evitar bloqueios potenciais.
  33. Nunca chamada IoAcquireCancelSpinLock na rotina de cancelar uma vez que denomina-se sempre com o sistema de cancelar o bloqueio de rotação mantidos em seu nome.
  34. Nunca esquecer-se chamar IoReleaseCancelSpinLock antes de devolver a partir de uma rotina de cancelamento.
  35. Nunca utilize sincronização com o IRQL porque isto funciona apenas em sistemas de processador único. Aumentar IRQL num processador máscara não interrupções nos outros processadores.
  36. Nunca utilize RtlCopyMemory para intervalos de endereço de memória sobrepostas. Utilização RtlMoveMemory.
  37. Nunca assumem tamanhos de página são constantes, mesmo para uma determinada CPU. Utilização PAGE_SIZE e outra página relacionadas constantes definidas no cabeçalho de ficheiros para manter a portabilidade.
  38. Nunca aceder quaisquer chaves de registo diferente Registry\Machine\Hardware e Registry\Machine\System a partir da rotina de DriverEntry de um controlador carregado na fase de inicialização de Boot\System.
  39. Nunca crie uma chave Enum para carregar um controlador de chave de registo do controlador (Registry\Machine\System\CurrentControlSet\Services). O sistema cria esta chave dinamicamente.
  40. Nunca tentativa para iniciar um dispositivo físico sem que afirma a portas de E/s bus relativo necessárias, intervalos de memória, interrupção ou acesso directo à memória (DMA) canal/porta recursos de hardware no registo pela primeira vez.
  41. Nunca chamar IoRegisterDriverReinitialization a partir de DriverEntry rotina a menos que devolver STATUS_SUCCESS.
  42. Nunca chamar KeSetEvent com o conjunto de parâmetro de espera para TRUE a partir de um thread paginável ou controlador paginável rotina que é executado no IRQL PASSIVE_LEVEL. Este tipo de chamada provoca uma falha de página fatal se a rotina ser paginada fora entre as chamadas para KeSetEvent e KeWaitObjecto (s).
  43. Nunca chamar KeReleaseSemaphore com o conjunto de parâmetro de espera para TRUE a partir de um thread paginável ou controlador paginável rotina que é executado no IRQL PASSIVE_LEVEL. Se a rotina ser paginada fora entre as chamadas para KeReleaseSemaphore e KeWaitObjecto (s de), este tipo de uma chamada provoca uma falha de página fatal.
  44. Nunca chamar KeReleaseMutex com o conjunto de parâmetro de espera para TRUE a partir de um thread paginável ou controlador paginável rotina que é executado no IRQL PASSIVE_LEVEL. Se a rotina ser paginada fora entre as chamadas para KeReleaseMutex e KeWaitObjecto (s de), este tipo de uma chamada provoca uma falha de página fatal.
  45. Nunca chamar KeBugCheckEx ou KeBugCheck a partir de um controlador de Windows NT de revenda para trazer para baixo o sistema, a menos que o erro encontrado um erro crítico que poderia corromper a memória do sistema ou, eventualmente, fazer com que o sistema verificação de defeito. Tente sempre processar correctamente as condições de erro.
  46. Nunca assumem que uma rotina IoTimer será chamada com precisão um limite de um segundo porque os intervalos em que qualquer IoTimer determinado rotina denomina-se, em última análise, dependem da resolução do relógio do sistema.
  47. Nunca chamar interfaces de programação de aplicações (API) Win32s a partir de um controlador de dispositivo do modo kernel.
  48. Nunca utilize recursiva funções que podem causar a pilha de capacidade excedida porque pilha de modo kernel do thread chamada não crescer dinamicamente enquanto está a ser executado no modo de kernel.
  49. Nunca utilize apontadores de objecto de interrupção (PKINTERRUPT) que processa mais do que uma interrupção, para identificar um ISR de interrupções porque o endereço do objecto interrupção que obtém no ISR não sempre será o mesmo que recebeu de IoConnectInterrupt. Só deve utilizar o valor de ServiceContext que especificar no IoConnectInterrupt para identificar o dispositivo de interrupção actual.
  50. Nunca descarrega um controlador sem limpar CustomTimerDpc (KeCancelTimer). Se o DPC é desencadeado depois do controlador carregado, foi não existente-código de acesso e fazer com que o sistema verificação de erros.
  51. Nunca descarregar um controlador até todos os IRPs que tenham o CompletionRoutine de E/s do controlador definir em foram concluídas. Se o IRP obtém concluído pelo controlador inferior depois do controlador carregado, o sistema poderia tentar executar código inexistente e provocar a falha do sistema.
  52. Active nunca interrupção do dispositivo até que o controlador esteja preparado para processar. Deverá activar apenas depois do controlador totalmente inicializado e é seguro para o sistema para estruturas internas do controlador no ISR e DPC de toque.
  53. Nunca chamada fora do seu controlador mantendo um spinlock porque pode fazer com que um impasse.
  54. Nunca devolvido qualquer estado diferente de STATUS_MORE_PROCESSING_REQUIRED de CompletionRoutine a E/s para um IRP criado pelo controlador com IoBuildAsynchronousFsdRequest/IoAllocateIrp uma vez que o IRP não está preparado para conclusão relacionadas post-processing pelo Gestor de E/s. Tal um IRP deve ser libertado explicitamente (IoFreeIrp) pelo controlador. Se o IRP destina-se não a reutilização, pode ser libertado in a CompletionRoutine antes de devolver estado STATUS_MORE_PROCESSING_REQUIRED.
  55. Nunca atribuir um IRP com IoBuildSynchronousFsdRequest/IoBuildDeviceIoControlRequest num contexto thread arbitrário porque o IRP permanece associado ao thread (Irp-> ThreadListEntry) até que é libertado.
  56. Nunca chame IoInitializeIrp num IRP que lhe tenha sido atribuída com IoAllocateIrp com ChargeQuota parâmetro definido como TRUE. Quando aloca um IRP com ChargeQuota definido como TRUE, o Gestor de E/s mantém as informações sobre o conjunto a partir do qual atribuída a memória para o IRP num sinalizador interno do IRP.

    Quando chama IoInitializeIrp no tal um IRP, as informações de agrupamento atribuição perdem-se como esta função blindly zeros IRP todo. Isto conduz a Corrupção da memória quando libertar o IRP. Além disso, nunca reutilize um IRP que provém o Gestor de E/S. Se pretender reutilizar um IRP, deve atribuir os seus próprios utilizando IoAllocateIrp.
  57. Especifica nunca WaitMode como UserMode em KeWaitForSingleObject/KeWaitForMultipleObjects se o objecto for atribuído na pilha de thread chamada. Corollary deste é que se o objecto a ser aguardado for criado na pilha de função, tem de especificar KernelMode como WaitMode para impedir que a pilha de thread a ser paginada fora.
  58. Nunca adquira recursos, tais como ERESOURCES e FastMutex(Unsafe) no contexto de um thread de modo de utilizador sem proteger o código de uma secção crítica.

    Uma vez que a aquisição destes recursos não acciona o IRQL para APC_LEVEL, se o thread suspenso (efectuado através da Colocação em fila um APC) depois de adquiriu o recurso, poderia provocar impasse e comprometer a segurança do sistema. Por este motivo, deve adquirir esses recursos ou levantando explicitamente o IRQL APC_LEVEL ou numa secção crítica chamando KeEnterCriticalRegion.

Referências

Manual de estrutura de controlador de dispositivo da MSDN para Windows NT

Propriedades

Artigo: 186775 - Última revisão: 27 de julho de 2004 - Revisão: 2.1
A informação contida neste artigo aplica-se a:
  • Microsoft Win32 Device Driver Kit para Windows NT 3.51
  • Microsoft Win32 Device Driver Kit para 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 revisto ou traduzido por humanos. A Microsoft tem artigos traduzidos por aplicações (MT) e artigos traduzidos por tradutores profissionais. O objectivo é simples: oferecer em Português a totalidade dos artigos existentes na base de dados do suporte. Sabemos no entanto que a tradução automática não é sempre perfeita. Esta pode conter erros de vocabulário, sintaxe ou gramática? erros semelhantes aos que um estrangeiro realiza ao falar em Português. A Microsoft não é responsável por incoerências, erros ou estragos realizados na sequência da utilização dos artigos MT por parte dos nossos clientes. A Microsoft realiza actualizações frequentes ao software de tradução automática (MT). Obrigado.
Clique aqui para ver a versão em Inglês deste artigo: 186775
Exclusão de Responsabilidade para Conteúdo sem Suporte na KB
Este artigo foi escrito sobre produtos para os quais a Microsoft já não fornece suporte. Por conseguinte, este artigo é oferecido "tal como está" e deixará de ser actualizado.

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