Chris Cant - Writing Windows WDM Device Drivers

Здесь есть возможность читать онлайн «Chris Cant - Writing Windows WDM Device Drivers» весь текст электронной книги совершенно бесплатно (целиком полную версию без сокращений). В некоторых случаях можно слушать аудио, скачать через торрент в формате fb2 и присутствует краткое содержание. Город: Lawrence, Kansas 66046, ISBN: , Издательство: R & D Books, Жанр: Программирование, на английском языке. Описание произведения, (предисловие) а так же отзывы посетителей доступны на портале библиотеки ЛибКат.

Writing Windows WDM Device Drivers: краткое содержание, описание и аннотация

Предлагаем к чтению аннотацию, описание, краткое содержание или предисловие (зависит от того, что написал сам автор книги «Writing Windows WDM Device Drivers»). Если вы не нашли необходимую информацию о книге — напишите в комментариях, мы постараемся отыскать её.

Writing Windows WDM Device Drivers — читать онлайн бесплатно полную книгу (весь текст) целиком

Ниже представлен текст книги, разбитый по страницам. Система сохранения места последней прочитанной страницы, позволяет с удобством читать онлайн бесплатно книгу «Writing Windows WDM Device Drivers», без необходимости каждый раз заново искать на чём Вы остановились. Поставьте закладку, и сможете в любой момент перейти на страницу, на которой закончили чтение.

Тёмная тема
Сбросить

Интервал:

Закладка:

Сделать

NTSTATUS Wdm1Read( IN PDEVICE_OBJECT fdo. IN PIRP Irp)

A dispatch routine is usually called at PASSIVE_LEVEL IRQL. (This is a bit unexpected, as you might expect dispatch routines to run at DISPATCH_LEVEL IRQL.) Running at PASSIVE_ LEVEL means that a dispatch routine can very easily be interrupted by other parts of the kernel or even your own driver. However, a routine that runs at PASSIVE_LEVEL can issue most kernel calls, including writing to other files.

A dispatch routine can be called at DISPATCH_LEVEL if a higher level driver calls you at this IRQL level. This might happen if it calls you from a completion routine, as described in Chapter 9. If you think this might be happening, then assume that your driver dispatch routines are running at DISPATCH_LEVEL

Dispatch routines run in an arbitrary thread context. As well as standard user mode threads, the kernel has its own threads that run only in kernel mode. Although your IRP will have originated in one of these threads, you cannot guarantee that you arc running in its context. This means that a valid address in the originating thread may not be valid when your driver sees it. A later section in this chapter shows how to access user buffers correctly.

Reentrancy

A dispatch routine must be reentrant. This means that it may be called "simultaneously" to process two separate IRPs. In a multiprocessor Windows 2000 system, one processor could call Wdm1Read with one IRP, and a second process on another CPU could also call Wdm1Read simultaneously with another IRP. However, do not dismiss reentrancy as some arcane requirement that your driver will never encounter. In Windows 98, the single processor could start running Wdm1Read to handle a first IRP. Wdm1Read could issue a kernel request that blocks its operation [14] Blocking in dispatch routines is not recommended as it defeats the purpose of overlapped operations. . Windows 98 might then schedule a different user application that issues another read resulting in another call to Wdm1Read .

The first technique to make your routine reentrant is to use local variables. Each separate call to Wdm1Read definitely has its own separate set of variables on the kernel stack.

Do not use global variables or variables in the device extension unless you protect access to them. However, when these variables are first set up (DriverEntry or AddDevice), you do not need to take special precautions.

The Wdm1 driver uses a spin lock to protect access to the shared memory buffer variables, as described later.

There are two other main techniques to achieve reentrancy in dispatch routines. The first is to use the services of the I/O Manager to create a device queue of IRPs. The IRPs in the device queue are passed one at a time to a StartIo routine in your driver.

The second technique is to use Critical section routines if your device interrupts the computer, as explained in full in Chapter 16. Calling KeSynchronizeExecution runs your Critical section routine safely. KeSynchronizeExecution raises the IRQL to the interrupt IRQL and acquires the interrupt spin lock. This technique ensures that your routine is run to completion without being interrupted by another part of the driver.

IRP Handling

There are three main techniques for handling IRPs.

• Handle immediately

• Put in a queue and process one by one

• Pass down to a lower-level driver

Only the simplest drivers, like Wdm1, can handle IRPs straightaway. Even so, you must still take precautions to ensure that your driver dispatch routines are reentrant.

Drivers that access real pieces of hardware usually want to serialize access to the hardware. As mentioned previously, the I/O Manager in the kernel provides a device queue that you can use. Dispatch routines call the kernel to put an IRP into the device queue. The I/O Manager calls your StartIo routine to process one IRP at a time. When your StartIo routine has completed an IRP, it should call the kernel to ensure that it is called again with the next available IRP.

Drivers might want to use more than one device queue. For example, a serial port driver will usually want to have two device queues; one for incoming read data and one for outgoing write data.

A driver can use a different queuing strategy. For example, the DebugPrint driver described in Chapter 14 lets only one read IRP be queued. Any further read IRPs are rejected while the first read IRP is outstanding.

The final main technique for handling IRPs is to pass them down for handling in a lower-level driver. This approach is common in WDM device drivers. Some drivers simply pass the handling of some IRPs to the next lower driver and forget about them. If you take a more active interest, you can inspect the results after all the lower-level drivers have handled the IRP. These techniques are covered later.

A variant on this theme is for a driver to build a new IRP (or IRPs), send it down to lower drivers, and process the results afterwards.

IRP Completion

When a driver has finished working on an IRP, it must tell the I/O Manager. This is called IRP completion. As this code snippet shows, you must set a couple of fields in the IRP IoStatus field structure. IoStatus.Status is set to an NTSTATUS status code. The number of bytes transferred is usually stored in IoStatus.Information.

Irp->IoStatus.Status = STATUS_SUCCESS;

Irp->IoStatus.Information = BytesTxd;

IoCompleteRequest(Irp,IO_NO_INCREMENT);

Finally, IoCompleteRequest is called (at or below DISPATCH_LEVEL IRQL). As well as the IRP pointer, you must supply a PriorityBoost parameter to give a boost to the scheduling priority of the thread that originated the IRP. For example, keyboard drivers use the constant IO_KEYBOARD_INCREMENT. This is a high value of 6 because foreground threads should respond quickly to user input.

If a dispatch routine does not process an IRP immediately, it must mark the IRP as pending using IoMarkIrpPending and return STATUS_PENDING. When you eventually get round to completing the IRP, do it as described above.

If an IRP is queued and its associated process dies unexpectedly (or calls CancelIo to cancel overlapped IRPs), these pending IRPs must be cancelled. You must set an IRP's cancel routine to handle this circumstance, and to handle the Cleanup IRP. Chapter 16 describes these options in full. Wdm1 does not queue IRPs, so handling these options is not necessary.

IRP Structure

Figure 7.1 shows that an I/O Request Packet consists of a header IRP structure followed by a series of stack locations, each an IO_STACK_LOCATION structure. The information in the header and the current IRP stack location tell a driver what to do.

Figure 7.1 IRP overview

Table 7.2 lists some of the fields in the IRP header structure that a driver can access, while Table 7.3 gives the general layout of the IO_STACK_LOCATION structure.

Table 7.2 Some IRP structure fields

Field Description
IO_STATUS_BLOCK IoStatus Completion status of IRP
PVOID AssociatedIrp.SystemBuffer System space buffer (for Buffered I/O)
PMDL MdlAddress Memory Description List (for Direct I/O)
BOOLEAN Cancel Set if IRP has been cancelled
ULONG Flags IRP Flags

Table 7.3 Some IO_STACK_LOCATION structure fields

typedef struct _IO_STACK_LOCATION {

Читать дальше
Тёмная тема
Сбросить

Интервал:

Закладка:

Сделать

Похожие книги на «Writing Windows WDM Device Drivers»

Представляем Вашему вниманию похожие книги на «Writing Windows WDM Device Drivers» списком для выбора. Мы отобрали схожую по названию и смыслу литературу в надежде предоставить читателям больше вариантов отыскать новые, интересные, ещё непрочитанные произведения.


Отзывы о книге «Writing Windows WDM Device Drivers»

Обсуждение, отзывы о книге «Writing Windows WDM Device Drivers» и просто собственные мнения читателей. Оставьте ваши комментарии, напишите, что Вы думаете о произведении, его смысле или главных героях. Укажите что конкретно понравилось, а что нет, и почему Вы так считаете.

x