ИНФОРМАЦИЯ: Советы по Windows NT Driver разработчики--предотвратить

Переводы статьи Переводы статьи
Код статьи: 186775 - Vizualiza?i produsele pentru care se aplic? acest articol.
Развернуть все | Свернуть все

Аннотация

Ниже приведены некоторые советы по созданию драйверов устройств Windows NT. Советы представленные применяются для всех технологий. Можно также использовать это в качестве контрольный список для устранения неполадок с драйвером.

Необходимо иметь базовые знания архитектуры Windows NT и некоторых использовать сведения, представленные ниже возможности разработки драйверов устройств эффективно. Дополнительные сведения о разработке драйверов устройств обратитесь к набор драйверов устройств Windows NT (DDK), который доступен через MSDN Профессиональное членство.

Дополнительная информация

Ниже приведен список вещей, которые разработчики должны избегать при работе с драйверами устройств Windows NT:

  1. Никогда не возвращает ответ STATUS_PENDING из подпрограммы диспетчеризации без маркировки Ввод-вывод пакет запроса (IRP) ожидающие (IoMarkIrpPending).
  2. Никогда не вызовет KeSynchronizeExecution из запроса прерывания (ISR). Он заблокируется системы.
  3. Никогда не указывайте DeviceObject-> флаги для DO_BUFFERED_IO и DO_DIRECT_IO. Может запутать системы и в итоге привести к неустранимой ошибке. Кроме того, никогда не указывайте METHOD_BUFFERED, METHOD_NEITHER, METHOD_IN_DIRECT или METHOD_OUT_DIRECT в DeviceObject-> флаги, поскольку эти значения являются только используется в определении IOCTL.
  4. Никогда не выделить объекты dispatcher из выгружаемого пула. В противном случае он будет вызвать завершила время от времени системы.
  5. Никогда не выделить память из выгружаемого пула или доступ к памяти в выгружаемом пуле При работе на уровне IRQL, > = DISPATCH_LEVEL. Он является неустранимой ошибкой.
  6. Никогда не ожидать на объект dispatcher ядра ненулевое значение интервала прерывания IRQL. > = DISPATCH_LEVEL. Он является неустранимой ошибкой.
  7. Никогда не вызвать любую функцию, вызывающий поток ждать непосредственно или косвенно, во время выполнения на уровне IRQL, > = DISPATCH_LEVEL. Он является неустранимым Ошибка.
  8. Никогда не ниже уровня, на котором понизить уровень запроса прерывания (IRQL) в вызове процедурой верхнего уровня.
  9. Никогда не вызовет KeLowerIrql(), если не был вызван KeRaiseIrql().
  10. Никогда не приводят к ожиданию процессора (KeStallExecutionProcessor) более чем 50 мкс.
  11. Никогда не удерживает никаких блокировок spin, дольше, чем необходимо. Для повышения общей производительность системы, не удерживать все общесистемные счетчик блокировок, длиннее, чем 25 микросекунды.
  12. Никогда не вызовет KeAcquireSpinLock и KeReleaseSpinLock, или KeAcquireSpinLockAtDpcLevel и KeReleaseSpinLockFromDpcLevel, тогда как Запуск прерывания IRQL больше, чем DISPATCH_LEVEL.
  13. Никогда не освобождать спин-блокировок, который был приобретен с KeAcquireSpinLock путем вызова KeReleaseSpinLockFromDpcLevel, так как исходный уровень прерывания IRQL будет не будут восстановлены.
  14. Никогда не вызовет KeAcquireSpinLock и KeReleaseSpinLock или любой другой процедуры, которая использует руководителей спин-блокировок ISR или SynchCritSection Routine(s).
  15. Никогда не забудьте снять флаг DO_DEVICE_INITIALIZING, при создании объект устройства в подпрограмме, отличные от DriverEntry.
  16. Никогда не ставить в очередь объекта вызова (DPC) отложенных процедур (с помощью KeInsertQueueDpc) с несколькими потоками на разных процессорах одновременно. Это может привести к неустранимой ошибке.
  17. Никогда не освобождать периодический таймер из подпрограммы CutomerTimerDPC. Можно освободить непериодических значений длиной таймеры из подпрограммы DPC.
  18. Никогда не передать же DPC указатель KeSetTimer или KeSetTimerEx (CustomTimerDpc) и KeInsertQueueDpc (CustomDpc), так как это вызывает гонки.
  19. Никогда не вызовет IoStartNextPacket при удерживании спин-блокировок. Он может к остановке системы.
  20. Никогда не вызовет IoCompleteRequest при удерживании спин-блокировок. Он может к остановке системы.
  21. Никогда не вызовет IoCompleteRequest без указания процедура завершения значение NULL, если драйвер устанавливается процедура завершения.
  22. Не забудьте задать блок состояния ввода-вывода в IRP перед вызовом метода IoCompleteRequest.
  23. Вызов никогда не IoMarkPending после очереди IRP или отправить его на другой драйвер (IoCallDriver). ЗАПРОС может выполняться до драйвер вызывает IoMarkPending и критической ошибки могут возникнуть. Для драйверов с процедуры завершения процедуры завершения должны вызывать IoMarkPending, если Задать IRP-> PendingReturned.
  24. Никогда не прикасайтесь IRP, после вызова IoCompleteRequest на нем.
  25. Вызов никогда не IoCancelIrp на IRP, который не принадлежит драйвер Если вы не знаете что запрос не был завершен.
  26. Никогда не IoCancelIrp для вызова IRP, подпрограмма диспетчеризации Работа на до ваших повседневных возврата диспетчеризации для вызывающего объекта.
  27. Никогда не вызывают IoMakeAssociatedIrp для создания IRP для драйверов нижнего уровня от промежуточного драйвера. IRP, вы получаете в промежуточного драйвера может быть связан IRP, а не может сопоставить другие IRP для уже связанные IRP.
  28. Вызов никогда не IoMakeAssociatedIrp на IRP, который настроен для выполнения буферизованный ввод-вывод.
  29. Никогда не просто разыменования виртуальные указатели на регистры устройства ввода/вывода и доступ к ним. Всегда используйте правильный аппаратных абстракций (HAL) функции для доступа к устройству.
  30. Доступ к не IRP или устройство полей объектов из ISR, которая может быть изменения из DISPATCH_LEVEL. В системе симметричных многопроцессорных это может привести к повреждению данных.
  31. Никогда не изменять данные во время выполнения на уровне IRQL высокой, если эти данные могут быть записать код низкий уровень IRQL. С помощью процедуры KeSynchronizeExecution.
  32. Никогда не получить один из драйверов спин-блокировки (если имеются) Подпрограмма DispatchCleanup перед установкой системных Отмена счетчик блокировки (IoAcquireCancelSpinLock). Следуя согласованности блокировок важно предотвращение приобретения иерархии по всему драйвер потенциальных взаимоблокировок.
  33. Никогда не вызовет IoAcquireCancelSpinLock в подпрограмму отмены, так как он всегда вызывается системой Отмена спин-блокировок удерживаются от своего имени.
  34. Не забудьте вызвать IoReleaseCancelSpinLock перед возвратом из Отмените процедуру.
  35. Никогда не используйте синхронизации на основе прерывания IRQL, так как это работает только на однопроцессорными системами. Вызов прерывания IRQL на один процессор не маски прерывания для других процессоров.
  36. Никогда не используйте RtlCopyMemory для памяти перекрывающихся диапазонов адресов. Использование RtlMoveMemory.
  37. Никогда не полагайте, размеры страницы являются постоянными, даже для данного Процессора. Использование PAGE_SIZE и других связанных констант, определенных в файлы заголовков на странице поддерживать переносимости.
  38. Доступ к разделы реестра, отличных от Registry\Machine\Hardware и Registry\Machine\System из процедуры DriverEntry загружен драйвер в фазе инициализации Boot\System.
  39. Никогда не создать ключ перечисления для загрузки драйвера в списке драйвер раздел реестра (Registry\Machine\System\CurrentControlSet\Services). В система динамически создает этот раздел.
  40. Никогда не пытаются Инициализация физического устройства без заявки необходимые порты ввода/вывода шины относительно, диапазон памяти, прерывание или прямой канал доступа к памяти (DMA) и порта аппаратных ресурсов в реестре первый.
  41. Никогда не вызовет IoRegisterDriverReinitialization из вашего DriverEntry процедуры, если он возвращает STATUS_SUCCESS.
  42. Никогда не KeSetEvent вызов с помощью параметра Wait значение TRUE из со страничной организацией потока или выгружаемой драйвер процедуры, запускаемой прерывания IRQL. PASSIVE_LEVEL. Этот тип вызова вызывает сбой, неустранимая страницы, если ваш процедура происходит с постраничный вывод между вызовами для KeSetEvent и KeWait...Объекты.
  43. Никогда не KeReleaseSemaphore вызов с помощью параметра Wait значение TRUE из страничной потока или выгружаемой драйвер процедуры, запускаемой прерывания IRQL. PASSIVE_LEVEL. Если постраничный вывод между вызовами подпрограмма KeReleaseSemaphore и KeWait...Объекты, этот тип вызова вызывает Ошибка Неустранимая страницы.
  44. Никогда не KeReleaseMutex вызов с помощью параметра Wait значение TRUE из со страничной организацией потока или выгружаемой драйвер процедуры, запускаемой прерывания IRQL. PASSIVE_LEVEL. Если постраничный вывод между вызовами подпрограмма KeReleaseMutex и KeWait...Объекты, этот тип вызова вызывает страница Неустранимая ошибка.
  45. Никогда не вызывают KeBugCheckEx или KeBugCheck из драйверов Windows NT розничной торговли вывести из строя системы, если не обнаружена ошибка является критической Ошибка, которая может привести к повреждению памяти системы или со временем привести к системе для отладки. Всегда пытается корректно обрабатывать ошибки.
  46. Никогда не полагайте, что процедура IoTimer будет вызываться точно на один- второй границу, так как интервалы времени, в которой любой конкретной IoTimer процедура вызывается в конечном счете зависит от разрешающей способности системных часов.
  47. Никогда не вызовет Win32s интерфейсов прикладного программирования (API) от драйвера устройства режима ядра.
  48. Никогда не использовать рекурсивные функции, которые может привести к переполнению стека так как стек ядра вызывающий поток не будет увеличиваться динамически во время работы в режиме ядра.
  49. Никогда не использовать прерывание указателей объектов (PKINTERRUPT) для идентификации прерывания в ISR, который выполняет более одного канала прерывания, поскольку адрес прерывания вы получаете в ISR не всегда будет тот же, полученную от IoConnectInterrupt. Следует использовать только ServiceContext значение, указанное в IoConnectInterrupt для Идентификация текущему устройству прерывания.
  50. Никогда не выгрузки драйвера без очистки CustomTimerDpc (KeCancelTimer). Если DPC срабатывает после выгрузки драйвера, его генералов не отсутствует код и заставляет систему отладки.
  51. Никогда не выгрузки драйвера до всех IRP, имеющих ввода-вывода CompletionRoutine драйвер, в ней выполняются. Если запрос возвращает дополнено нижнего драйвера после драйвер выгружен, система может попытаться выполнить несуществующий код и привести к сбою системы.
  52. Никогда не разрешайте прерывание устройства, пока драйвер не будет готов обработать его. Следует включать только после инициализации драйвера и можно безопасно touch драйвер внутренних структур в системе ISR и DPC.
  53. Никогда не вызывать вне драйвер при удерживании спин-блокировки, так как он может привести к взаимоблокировке.
  54. Никогда не возврата любое состояние, отличное от STATUS_MORE_PROCESSING_REQUIRED из вашего CompletionRoutine ввода-вывода для IRP, созданные драйвер с помощью функции IoBuildAsynchronousFsdRequest и IoAllocateIrp, поскольку запрос не подготовлен для завершения связанных постобработки, диспетчер ввода-вывода. Такие IRP следует явно освобожден (IoFreeIrp), драйвер. Если запрос не предназначен для повторного использования, ее можно освободить в CompletionRoutine перед возвратом состояния STATUS_MORE_PROCESSING_REQUIRED.
  55. Никогда не выделить IRP с IoBuildSynchronousFsdRequest/IoBuildDeviceIoControlRequest в Произвольный поток контекста, поскольку IRP остается связанных с поток (Irp-> ThreadListEntry) до его освобождения.
  56. Никогда не вызывать IoInitializeIrp IRP, была выделена с помощью функции IoAllocateIrp со значением параметра ChargeQuota значение TRUE. При распределении IRP с ChargeQuota равным TRUE, диспетчер ввода-вывода сохраняет сведения о пуле, из которого он выделяет память для IRP в IRP внутреннего флага.

    При вызове IoInitializeIrp на таких IRP распределения пула теряется как эта функция вслепую нули всего IRP. Это приводит к повреждению памяти при освобождении IRP. Никогда не использовать IRP, которые поступают от диспетчера ввода-ВЫВОДА. Если вы хотите повторно использовать IRP, следует выделить свой собственный с помощью функции IoAllocateIrp.
  57. Никогда не указать режим ожидания как пользовательского режима в KeWaitForSingleObject/KeWaitForMultipleObjects, если выделенный объект в стеке вызывающего потока. Этот аспект является, при которой ожидается объект создается в стеке функции, необходимо определить KernelMode как режим ожидания, чтобы предотвратить стека потока постраничный вывод.
  58. Никогда не получить ресурсы, такие как ERESOURCES и FastMutex(Unsafe) в контексте потока пользовательского режима без защиты кода в критический раздел.

    Поскольку приобретения этих ресурсов не вызывает IRQL для APC_LEVEL, если поток приостановлен (выполнено по очереди APC) после присвоения ресурса, это может привести к взаимоблокировке и нарушению защиты системы. Таким образом следует приобрести такие ресурсы, либо путем явного вызова прерывания IRQL, APC_LEVEL или в критический раздел путем вызова KeEnterCriticalRegion.

Ссылки

Руководство по созданию драйверов устройств MSDN для Windows NT

Свойства

Код статьи: 186775 - Последний отзыв: 4 июня 2011 г. - Revision: 4.0
Информация в данной статье относится к следующим продуктам.
  • Microsoft Win32 Device Driver Kit for Windows NT 4.0
Ключевые слова: 
kbinfo kbmt KB186775 KbMtru
Переведено с помощью машинного перевода
ВНИМАНИЕ! Перевод данной статьи был выполнен не человеком, а с помощью программы машинного перевода, разработанной корпорацией Майкрософт. Корпорация Майкрософт предлагает вам статьи, переведенные как людьми, так и средствами машинного перевода, чтобы у вас была возможность ознакомиться со статьями базы знаний KB на родном языке. Однако машинный перевод не всегда идеален. Он может содержать смысловые, синтаксические и грамматические ошибки, подобно тому как иностранец делает ошибки, пытаясь говорить на вашем языке. Корпорация Майкрософт не несет ответственности за неточности, ошибки и возможный ущерб, причиненный в результате неправильного перевода или его использования. Корпорация Майкрософт также часто обновляет средства машинного перевода.
Эта статья на английском языке:186775
Заявление об отказе относительно содержимого статьи о продуктах, поддержка которых прекращена
Эта статья содержит сведения о продуктах, поддержка которых корпорацией Майкрософт прекращена. Поэтому она предлагается как есть и обновляться не будет.

Отправить отзыв

 

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