연결 잠금은 두 클라이언트가 간단한 SPB(주변 장치 버스 )에서 대상 주변 디바이스에 대한 액세스를 공유할 수 있도록 하는 데 유용합니다. 두 클라이언트는 동일한 대상 디바이스에 대한 논리적 연결을 열고 두 클라이언트가 일련의 I/O 작업을 수행하기 위해 디바이스에 단독으로 액세스해야 하는 경우 연결 잠금을 사용할 수 있습니다. 한 클라이언트가 연결 잠금을 보유하면 두 번째 클라이언트가 디바이스에 액세스하는 요청은 첫 번째 클라이언트가 잠금을 해제할 때까지 자동으로 지연됩니다.
클라이언트는 IOCTL_SPB_LOCK_CONNECTION 및 IOCTL_SPB_UNLOCK_CONNECTION 요청을 사용하여 SPB의 대상 디바이스에서 연결 잠금을 획득하고 해제합니다. 클라이언트는 이러한 I/O 컨트롤(IOCTL) 요청을 디바이스의 파일 개체로 보냅니다.
SPB에 연결된 주변 장치용 드라이버는 일반적으로 User-Mode UMDF(드라이버 프레임워크) 드라이버 또는 KMDF(Kernel-Mode 드라이버 프레임워크) 드라이버입니다. SPB에 연결된 주변 디바이스에 IOCTL 요청을 보내기 위해 UMDF 드라이버는 IWDFIoRequest::Send와 같은 메서드를 호출합니다. KMDF 드라이버는 WdfIoTargetSendIoctlSynchronously와 같은 메서드를 호출합니다.
일반적으로 연결 잠금은 필요하지 않습니다. 대부분의 클라이언트 드라이버는 항상 SPB의 대상 디바이스에 단독으로 액세스할 수 있습니다. 연결 잠금은 두 클라이언트가 동일한 대상 디바이스에 대한 액세스를 공유해야 하는 비교적 드문 경우에만 필요하며, 하나 또는 두 클라이언트 모두 일련의 I/O 작업을 위해 디바이스에 대한 단독 액세스 권한이 있어야 합니다.
기본적으로 두 클라이언트가 대상 디바이스를 공유하는 경우 SPB 프레임워크 확장 (SpbCx)은 SpbCx 요청 큐에 도착하는 순서에 따라 디바이스에 대한 I/O 요청을 직렬화합니다. 연결 잠금은 요청의 기본 순서를 재정의합니다. 한 클라이언트가 연결 잠금을 획득하면 SpbCx는 첫 번째 클라이언트가 잠금을 해제할 때까지 두 번째 클라이언트에서 수신하는 I/O 요청을 다시 보유합니다.
SpbCx의 현재 구현에서 연결 잠금의 기본 사용은 대상 디바이스에 대한 클라이언트 드라이버가 ACPI 드라이버 Acpi.sys디바이스에 대한 액세스를 공유할 수 있도록 하는 것입니다. Acpi.sys 하드웨어 플랫폼용 ACPI 펌웨어를 대신하여 특정 코어 리소스 디바이스를 관리하는 시스템 제공 드라이버입니다. 예를 들어 SoC(System on a Chip)를 사용하는 플랫폼에는 Acpi.sys 클라이언트 드라이버 둘 다에서 액세스하는 PMIC(전원 관리 통합 회로)도 포함될 수 있습니다.
클라이언트 드라이버는 대상 디바이스에 대한 단독 액세스가 필요한 I/O 작업에 대한 연결 잠금이 필요한지 여부를 결정합니다. 드라이버가 일부 하드웨어 플랫폼 또는 플랫폼 구성에서 연결 잠금이 필요하지만 다른 하드웨어 플랫폼 구성에서는 필요하지 않은 경우 드라이버 개발자와 플랫폼 개발자는 연결 잠금을 사용할 시기를 결정하기 위한 드라이버별 메커니즘에 동의해야 합니다. 일반적으로 연결 잠금을 사용할지 여부에 대한 정보는 플랫폼 펌웨어에 포함됩니다. 예를 들어 디바이스에 대한 ACPI 리소스 설명자의 공급업체 정의 정보 블록에는 드라이버가 디바이스를 Acpi.sys공유하는지 여부를 나타내는 플래그 비트가 포함될 수 있습니다.
연결 잠금 예제
연결 잠금의 일반적인 사용은 원자성 읽기-수정-쓰기 작업을 구현하는 것입니다. 두 클라이언트가 간단한 SPB(주변 버스)에서 동일한 대상 디바이스에 대한 액세스를 공유하는 경우 두 클라이언트는 연결 잠금을 사용하여 읽기 작업과 쓰기 작업을 원자성 읽기-수정-쓰기 작업 하나에 병합할 수 있습니다. 연결 잠금을 사용하면 다른 클라이언트가 읽기 및 쓰기 작업 간에 대상 디바이스에 액세스할 수 없게 됩니다.
다음 목록에서는 클라이언트가 SPB에 연결된 대상 디바이스에 전송하여 디바이스에서 읽기-수정-쓰기 작업을 수행할 수 있는 일련의 I/O 요청에 대해 설명합니다.
- IOCTL_SPB_LOCK_CONNECTION – 대상 디바이스에서 연결 잠금을 획득합니다.
- IRP_MJ_READ – 클라이언트가 데이터를 해석하고 수정할 수 있도록 디바이스 주소에서 데이터 블록을 읽습니다.
- IRP_MJ_WRITE – 수정된 데이터 블록을 디바이스 주소에 씁니다.
- IOCTL_SPB_UNLOCK_CONNECTION – 대상 디바이스에서 연결 잠금을 해제합니다.
앞의 목록은 단일 디바이스 함수를 구현하는 간단한 디바이스에 적합할 수 있습니다.
그러나 더 복잡한 디바이스는 여러 디바이스 기능을 구현할 수 있습니다. 이 디바이스에는 클라이언트가 데이터 전송을 시작할 때 로드하는 함수 주소 레지스터가 포함될 수 있습니다. 이 디바이스의 경우 IOCTL_SPB_EXECUTE_SEQUENCE 요청은 함수 주소 레지스터의 로드와 그 다음에 나오는 데이터 전송을 단일 원자 버스 작업으로 결합할 수 있습니다. 자세한 내용은 Atomic Bus 작업의 예제 I2C 디바이스에 대한 설명을 참조하세요.
컨트롤러 잠금과 비교
클라이언트는 연결 잠금을 사용하여 대상 디바이스에 대한 단독 액세스를 가져오지만 연결 잠금으로 인해 버스의 다른 디바이스와 데이터 전송이 차단되지는 않습니다.
일련의 데이터 전송을 원자 버스 작업으로 수행하기 위해 클라이언트는 일반적으로 IOCTL_SPB_EXECUTE_SEQUENCE 요청을 사용합니다. 원자 버스 작업을 수행하는 덜 일반적인 방법은 컨트롤러 잠금을 사용하는 것입니다. 클라이언트 는 컨트롤러 잠금을 획득하고 해제하기 위해 IOCTL_SPB_LOCK_CONTROLLER 및 IOCTL_SPB_UNLOCK_CONTROLLER 요청을 보냅니다.
컨트롤러 잠금은 연결 잠금과 다릅니다. 컨트롤러 잠금을 사용하면 버스의 대상 디바이스와 오가는 일련의 I/O 전송을 단일 원자 버스 작업으로 수행할 수 있습니다. 컨트롤러 잠금이 적용되는 동안 컨트롤러 잠금이 해제될 때까지 버스의 다른 장치 간에 전송이 지연됩니다. 자세한 내용은 Atomic Bus 작업을 참조하세요.
비고
일부 구현에서는 연결 잠금이 부작용으로 인해 버스의 다른 디바이스로의 전송을 방지할 수 있습니다. 그러나 이 동작은 구현에 따라 달라지며 클라이언트 드라이버는 이를 사용하지 않아야 합니다. 반면 컨트롤러 잠금은 다른 클라이언트가 컨트롤러 잠금을 보유하는 클라이언트와 동일한 대상 디바이스에 액세스하지 못하게 하며 클라이언트는 이 동작에 안전하게 의존할 수 있습니다.
대상 디바이스에서 일련의 I/O 작업을 수행하기 전에 클라이언트가 연결 잠금과 컨트롤러 잠금을 모두 획득해야 할 수 있습니다. 연결 잠금은 동일한 대상 디바이스에 대한 액세스를 공유하는 두 번째 클라이언트가 디바이스에서 I/O 작업을 수행할 수 없도록 하고 컨트롤러 잠금은 버스의 다른 디바이스에 대한 클라이언트가 이러한 다른 디바이스에서 I/O 작업을 수행할 수 없도록 합니다. (잠금이 유지되는 동안 발생하는 것을 방지하는 I/O 작업은 잠금이 해제될 때까지 단순히 지연됩니다.)
클라이언트가 SPB의 대상 디바이스에 대한 연결 잠금과 컨트롤러 잠금을 모두 획득하는 경우 클라이언트는 컨트롤러 잠금을 획득하기 전에 연결 잠금을 획득해야 하며 연결 잠금을 해제하기 전에 컨트롤러 잠금을 해제해야 합니다. 클라이언트가 연결 잠금을 획득한 후 클라이언트는 필요한 경우 클라이언트가 연결 잠금을 해제하기 전에 필요한 횟수만큼 컨트롤러 잠금을 획득하고 해제할 수 있습니다.
연결 잠금의 중첩된 획득은 불법입니다. 클라이언트가 연결 잠금을 획득한 후에는 클라이언트가 잠금을 처음 해제할 때까지 잠금을 다시 획득하려고 하면 안 됩니다. 마찬가지로 컨트롤러 잠금의 중첩된 획득은 허용되지 않습니다.