다음을 통해 공유


공유 상태 정보 액세스

Use the following general guidelines when designing and writing SynchCritSection routines that maintain state information:

  • To access data that an ISR also accesses, a driver routine must call a SynchCritSection routine. 비임계 섹션 코드는 중단될 수 있습니다. Remember that it's not sufficient to just acquire a spin lock to protect data that ISRs also access, because ISRs execute at DIRQL and acquiring a spin lock (KeAcquireSpinLock) only raises IRQL to DISPATCH_LEVEL, which allows an interrupt to invoke the ISR on the current processor.

  • Give each SynchCritSection routine that maintains state information responsibility for a discrete set of state variables. That is, avoid writing SynchCritSection routines that maintain overlapping state information.

    This approach prevents contention, and possibly race conditions, between SynchCritSection routines (and the ISR) trying to access the same state concurrently.

    This approach also ensures that each SynchCritSection routine returns control as quickly as possible. That is, one SynchCritSection routine never has to wait for another that updates some of the same state information to return control.

  • Avoid writing a single, large, general-purpose SynchCritSection routine that does more testing of conditions to determine what to do than actually doing useful work. On the other hand, avoid having many SynchCritSection routines that never execute a conditional statement because each updates only a single byte of state information.

  • Ensure every SynchCritSection routine returns control as quickly as possible, because running any SynchCritSection routine prevents the driver's ISR from executing.

다음 예제에서는 디바이스 확장에서 타이머 카운터를 유지 관리하는 방법을 보여줍니다. 드라이버가 카운터를 사용하여 I/O 작업의 시간 초과 여부를 확인한다고 가정합니다. 또한 드라이버가 I/O 작업과 겹치지 않는다고 가정합니다.

  1. The driver's StartIo routine initializes the timer counter to some initial value for each I/O request. The driver then adds a second to its device timeout value, in case its IoTimer routine just returned control.

  2. 드라이버의 ISR은 이 타이머 카운터를 빼기 1로 설정합니다.

  3. The driver's IoTimer routine is called once per second to read the time counter and determine whether the ISR already set it to minus one. If not, the IoTimer routine decrements the counter by using KeSynchronizeExecution to call a SynchCritSection_1 routine.

    요청 시간이 초과되었음을 나타내는 카운터가 0으로 이동하면 SynchCritSection_1 루틴은 SynchCritSection_2 루틴을 호출하여 디바이스 재설정 작업을 프로그래밍합니다. If the counter is minus one, the IoTimer routine simply returns.

  4. If the driver's DpcForIsr routine must reprogram the device to begin a partial-transfer operation, it must reinitialize the timer counter as the StartIo routine did.

    The DpcForIsr routine also must use KeSynchronizeExecution to call the SynchCritSection_2 routine, or possibly a SynchCritSection_3 routine, to program the device for another transfer operation.

In this scenario, the driver has more than one SynchCritSection routine, each with discrete, specific responsibilities: one to maintain its timer counter, and one or more others to program the device. Each SynchCritSection routine returns control quickly because it performs a single, discrete task.

드라이버에는 드라이버의 ISR과 함께 타이머 카운터에 상태를 유지하는 단일 SynchCritSection_1 루틴이 있습니다. Thus, there's no contention for access to the timer counter among several SynchCritSection routines and the ISR.