从Driver的主线程获取时,KSPIN_LOCK会阻塞

问题描述 投票:1回答:1

我有一个KSPIN_LOCK,它在Windows驱动程序的主线程和我用PsCreateSystemThread创建的一些线程之间共享。问题是如果我尝试获取自旋锁并且没有解除阻塞,则主线程会阻塞。我很困惑为什么会发生这种情况..它可能以某种方式与主线程在驱动程序IRQL上运行这一事实有关,而据我所知,其他线程在PASSIVE_LEVEL运行。

注意:如果我只运行主线程,获取/释放锁定工作正常。

注意:我正在使用KeAcquireSpinLockKeReleaseSpinLock函数来获取/释放锁。

windows multithreading kernel driver wdk
1个回答
1
投票

这是我的“卡住”螺旋锁的清单:

  1. 确保使用KeInitializeSpinLock初始化自旋锁。如果KSPIN_LOCK保留未初始化的垃圾,那么第一次尝试获取它可能会永远旋转。
  2. 检查您是否以递归方式/嵌套方式获取它。 KSPIN_LOCK不支持递归,如果你尝试它,它将永远旋转。
  3. 必须在IRQL <= DISPATCH_LEVEL处获取正常的自旋锁。如果您需要在DIRQL上工作的东西,请查看[1][2]
  4. 检查是否有泄漏。如果一个处理器获得了自旋锁,但忘记释放它,则下一个处理器将在尝试获取锁时永远旋转。
  5. 确保没有内存安全问题。如果代码在自旋锁上方随机写入一个非零值,那么它将导致它被获取,并且下一次获取将永远旋转。

使用Driver Verifier可以轻松自动捕获其中一些问题;如果你还没有使用它,请使用它。如果将spinlock封装在一个添加自己的断言的小助手中,则可以捕获其他问题。例如:

typedef struct _MY_LOCK {
    KSPIN_LOCK Lock;
    ULONG OwningProcessor;
    KIRQL OldIrql;
} MY_LOCK;

void MyInitialize(MY_LOCK *lock) {
    KeInitializeSpinLock(&lock->Lock);
    lock->OwningProcessor = (ULONG)-1;
}

void MyAcquire(MY_LOCK *lock) {
    ULONG current = KeGetCurrentProcessorIndex();
    NT_ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
    NT_ASSERT(current != lock->OwningProcessor); // check for recursion
    KeAcquireSpinLock(&lock->Lock, &lock->OldIrql);
    NT_ASSERT(lock->OwningProcessor == (ULONG)-1); // check lock was inited
    lock->OwningProcessor = current;
}

void MyRelease(MY_LOCK *lock) {
    NT_ASSERT(KeGetCurrentProcessorIndex() == lock->OwningProcessor);
    lock->OwningProcessor = (ULONG)-1;
    KeReleaseSpinLock(&lock->Lock, lock->OldIrql);
}

围绕KSPIN_LOCK的包装很常见。 KSPIN_LOCK就像一辆赛车,其所有可选功能都被剥离,以最大限度地提高原始速度。如果你不计算微秒,你可以合理地决定通过将低级别的KSPIN_LOCK包裹在上面这样的东西来加回加热座椅和FM收音机。 (有了#ifdefs的魔力,如果你需要,你可以随时从你的零售版本中取出安全气囊。)

© www.soinside.com 2019 - 2024. All rights reserved.