次の方法で共有


SPB 接続のロック

接続ロックは、2 つのクライアントが単純な周辺機器バス (SPB) 上のターゲット周辺機器へのアクセスを共有できるようにするのに役立ちます。 どちらのクライアントも、同じターゲット デバイスへの論理接続を開き、一連の I/O 操作を実行するためにデバイスへの排他アクセスが必要な場合に接続ロックを使用できます。 1 つのクライアントが接続ロックを保持すると、2 番目のクライアントによるデバイスへのアクセス要求は、最初のクライアントがロックを解放するまで自動的に遅延されます。

クライアントは、IOCTL_SPB_LOCK_CONNECTION 要求と IOCTL_SPB_UNLOCK_CONNECTION 要求を使用して、SPB 上のターゲット デバイスの接続ロックを取得して解放します。 クライアントは、デバイスのファイル オブジェクトにこれらの I/O コントロール (IOCTL) 要求を送信します。

SPB に接続された周辺機器のドライバーは、通常、ユーザー モード ドライバー フレームワーク (UMDF) ドライバーまたはカーネル モード ドライバー フレームワーク (KMDF) ドライバーのいずれかです。 SPB に接続された周辺機器に IOCTL 要求を送信するには、UMDF ドライバーは IWDFIoRequest::Send などのメソッドを呼び出します。 KMDF ドライバーは、WdfIoTargetSendIoctlSynchronously などのメソッドを呼び出します。

通常、接続ロックは不要です。 ほとんどのクライアント ドライバーは、常に SPB 上のターゲット デバイスへの排他的アクセス権を持っています。 接続ロックは、2 つのクライアントが同じターゲット デバイスへのアクセスを共有する必要があり、1 つまたは両方のクライアントが一連の I/O 操作のためにデバイスへの排他的アクセス権を持たなければならない比較的まれな場合にのみ必要です。

既定では、2 つのクライアントがターゲット デバイスを共有する場合、SPB フレームワーク拡張機能 (SpbCx) は、SpbCx 要求キューに到着した順序に従ってデバイスの I/O 要求をシリアル化します。 接続ロックは、要求の既定の順序をオーバーライドします。 1 つのクライアントが接続ロックを取得した後、SpbCx は、最初のクライアントがロックを解放するまで、2 番目のクライアントから受信する I/O 要求を保持します。

SpbCx の現在の実装では、接続ロックの主な用途は、ターゲット デバイスのクライアント ドライバーが ACPI ドライバー Acpi.sys とデバイスへのアクセスを共有できるようにすることです。 Acpi.sys は、ハードウェア プラットフォームの ACPI ファームウェアに代わって特定のコア リソース デバイスを管理するシステム提供のドライバーです。 たとえば、System on a Chip (SoC) を使用するプラットフォームには、Acpi.sys とクライアント ドライバーの両方からアクセスされる電源管理集積回路 (PMIC) も含まれている場合があります。

クライアント ドライバーは、ターゲット デバイスへの排他アクセスを必要とする I/O 操作の接続ロックが必要かどうかを判断する役割を担います。 ドライバーが一部のハードウェア プラットフォームまたはプラットフォーム構成では接続ロックを必要とするが、それ以外では必要がない場合、ドライバーの開発者とプラットフォーム開発者は、接続ロックを使用するタイミングを決定するためのドライバー固有のメカニズムに同意する必要があります。 通常、接続ロックを使用するかどうかに関する情報は、プラットフォーム ファームウェアに含まれています。 たとえば、デバイスの ACPI リソース記述子のベンダー定義情報ブロックには、ドライバーがデバイスを Acpi.sys と共有するかどうかを示すフラグ ビットが含まれている場合があります。

接続ロックの例

接続ロックの一般的な用途は、アトミックな読み取り/変更/書き込み操作を実装することです。 2 つのクライアントが単純な周辺機器バス (SPB) 上の同じターゲット デバイスへのアクセスを共有する場合、どちらのクライアントも接続ロックを使用して、読み取り操作と書き込み操作を 1 つのアトミックな読み取り/変更/書き込み操作にマージすることができます。 接続ロックにより、他のクライアントが読み取り操作と書き込み操作の間でターゲット デバイスにアクセスできなくなります。

次の一覧では、クライアントが SPB に接続されたターゲット デバイスに送信して、デバイスで読み取り/変更/書き込み操作を実行する一連の I/O 要求について説明します。

  1. IOCTL_SPB_LOCK_CONNECTION – ターゲット デバイスの接続ロックを取得します。
  2. IRP_MJ_READ – クライアントがデータを解釈および変更できるように、デバイス アドレスからデータブロックを読み取ります。
  3. IRP_MJ_WRITE – 変更したデータ ブロックをデバイス アドレスに書き込みます。
  4. IOCTL_SPB_UNLOCK_CONNECTION – ターゲット デバイスの接続ロックを解除します。

前述の一覧は、1 つのデバイス機能を実装する単純なデバイスに適している場合があります。

ただし、より複雑なデバイスでは、いくつかのデバイス機能が実装される場合があります。 このデバイスには、クライアントがデータ転送の開始時に読み込む関数アドレス レジスタが含まれている場合があります。 このデバイスの場合、IOCTL_SPB_EXECUTE_SEQUENCE 要求は、関数アドレス レジスタの読み込みと、その後のデータ転送を 1 つのアトミック バス操作に組み合わせることができます。 詳細については、「アトミック バス操作」の例「I2C デバイス」の説明を参照してください。

コントローラー ロックとの比較

クライアントは、接続ロックを使用してターゲット デバイスへの排他アクセスを取得しますが、接続ロックによって、バス上にある他のデバイスとの間のデータ転送は防止されません。

一連のデータ転送をアトミック バス操作として実行するには、通常、クライアントは IOCTL_SPB_EXECUTE_SEQUENCE 要求を使用します。 アトミック バス操作の実行において、あまり一般的ではない方法は、コントローラー ロックを使用することです。 クライアントは、 IOCTL_SPB_LOCK_CONTROLLER リクエストと IOCTL_SPB_UNLOCK_CONTROLLER リクエストを送信して、コントローラー ロックを取得および解放します。

コントローラー ロックは、接続ロックとは異なります。 コントローラー ロックにより、バス上のターゲット デバイスとの間の一連の I/O 転送を 1 つのアトミック バス操作として実行できます。 コントローラー ロックが有効な間、バス上の他のデバイス間の転送は、コントローラー ロックが解除されるまで遅延されます。 詳細については、「Atomic Bus Operations」を参照してください。

Note

一部の実装では、接続ロックが副作用として、バス上の他のデバイスへの転送を妨げる可能性があります。 ただし、この動作は実装に依存し、クライアント ドライバーはそれに依存すべきではありません。 これに対し、コントローラー ロックは、コントローラー ロックを保持しているクライアントと同じターゲット デバイスに別のクライアントがアクセスするのを確実に防ぎ、クライアントはこの動作に安全に依存できます。

クライアントは、ターゲット デバイスで一連の I/O 操作を実行する前に、接続ロックとコントローラー ロックの両方を取得する必要がある場合があります。 接続ロックにより、同じターゲット デバイスへのアクセスを共有する 2 番目のクライアントがデバイスで I/O 操作を実行できなくなります。また、コントローラー ロックにより、バス上の他のデバイスのクライアントがこれらの他のデバイスで I/O 操作を実行できなくなります。 (これらのロックが保持されている間に発生しないようにする I/O 操作は、ロックが解除されるまで遅延されます)。

クライアントが SPB 上のターゲット デバイスの接続ロックとコントローラー ロックの両方を取得する場合、クライアントはコントローラー ロックを取得する前に接続ロックを取得し、接続ロックを解除する前にコントローラー ロックを解除する必要があります。 クライアントが接続ロックを取得した後、クライアントは必要に応じて、接続ロックを解除する前に、必要な回数のコントローラー ロックを取得して解除できます。

接続ロックのネストされた取得は不正です。 接続ロックを取得した後、最初にロックを解除するまで、クライアントはロックの取得を再試行しないでください。 同様に、コントローラー ロックのネストされた取得は許可されません。