64비트 오디오 드라이버 작성
64비트 드라이버를 작성하거나 32비트 및 64비트 시스템에서 실행되도록 컴파일할 수 있는 드라이버를 작성하는 경우 드라이버 프로그래밍 기술의 포팅 지침을 따릅니다. 64비트 오디오 드라이버를 작성할 때 발생할 수 있는 몇 가지 문제는 아래에 설명되어 있습니다.
무엇보다도 기존 32비트 드라이버 코드에서 찾을 수 있는 잠재적인 문제는 포인터 형식과 DWORD 또는 ULONG과 같은 정수 형식 간의 변환입니다. 32비트 컴퓨터에 대한 코드를 작성한 경험이 있는 프로그래머는 포인터 값이 DWORD 또는 ULONG에 맞는다고 가정하는 데 사용할 수 있습니다. 64비트 코드의 경우 이 가정은 위험합니다. DWORD 또는 ULONG 형식으로 포인터를 캐스팅하면 64비트 포인터가 잘리게 될 수 있습니다. 더 나은 방법은 포인터를 형식 DWORD_PTR 또는 ULONG_PTR 캐스팅하는 것입니다. 코드가 32비트 또는 64비트 컴퓨터에 대해 컴파일되는지 여부에 관계없이 DWORD_PTR 또는 ULONG_PTR 형식의 부호 없는 정수는 항상 전체 포인터를 저장할 수 있을 만큼 큽니다.
예를 들어 IRP 포인터 필드 IoStatus입니다. 정보는 ULONG_PTR 형식입니다. 다음 코드에서는 이 필드에 64비트 포인터 값을 복사할 때 수행할 수 없는 작업을 보여 합니다.
PDEVICE_RELATIONS pDeviceRelations;
Irp->IoStatus.Information = (ULONG)pDeviceRelations; // wrong
이 코드 샘플은 포인터를 pDeviceRelations
ULONG 형식으로 잘못 캐스팅합니다. 이 경우 sizeof(pDeviceRelations) > sizeof(ULONG)
포인터 값을 잘라낼 수 있습니다. 올바른 방법은 다음과 같이 포인터를 ULONG_PTR 캐스팅하는 것입니다.
PDEVICE_RELATIONS pDeviceRelations;
Irp->IoStatus.Information = (ULONG_PTR)pDeviceRelations; // correct
이렇게 하면 포인터 값의 64비트 모두 유지됩니다.
리소스 목록은 리소스의 실제 주소를 PHYSICAL_ADDRESS 형식 구조에 저장합니다( IResourceList 참조). 64비트 주소가 잘리지 않도록 하려면 주소를 구조체로 복사하거나 구조체에서 주소를 읽을 때 LowPart 멤버가 아닌 구조체의 QuadPart 멤버에 액세스해야 합니다. 예를 들어 FindTranslatedPort 매크로는 I/O 포트의 기본 주소를 포함하는 CM_PARTIAL_RESOURCE_DESCRIPTOR 구조체에 대한 포인터를 반환합니다. u. 포트. 이 구조체의 시작 멤버는 기본 주소에 대한 PHYSICAL_ADDRESS 포인터입니다. 다음 코드는 수행하지 않는 작업을 보여줍니다.
PUSHORT pBase = (PUSHORT)FindTranslatedPort(0)->u.Port.Start.LowPart; // wrong
다시 말하지만 포인터를 잘라낼 수 있습니다. 대신 다음과 같이 이 멤버의 QuadPart 에 액세스해야 합니다.
PUSHORT pBase = (PUSHORT)FindTranslatedPort(0)->u.Port.Start.QuadPart; // correct
그러면 전체 64비트 포인터가 복사됩니다.
PtrToUlong 및 UlongToPtr과 같은 인라인 Win64 함수는 이러한 형식의 상대적 크기에 대한 가정을 사용하지 않고 포인터 형식과 정수 형식 간에 안전하게 변환합니다. 한 형식이 다른 형식보다 짧은 경우 더 긴 형식으로 변환할 때 확장해야 합니다. 각 Win64 함수에 대해 부호 비트를 채우거나 0으로 채워 짧은 형식을 확장할지 여부를 잘 정의합니다. 즉, 와 같은 모든 코드 조각
ULONG ulSlotPhysAddr[NUM_PHYS_ADDRS];
ulSlotPhysAddr[0] = ULONG(pulPhysDmaBuffer) + DMA_BUFFER_SIZE; // wrong
을 로 바꿔야 합니다.
ULONG_PTR ulSlotPhysAddr[NUM_PHYS_ADDRS];
ulSlotPhysAddr[0] = PtrToUlong(pulPhysDmaBuffer) + DMA_BUFFER_SIZE; // correct
이는 64비트 길이가 아닌 32비트인 하드웨어 레지스터의 값을 나타낼 수 있더라도 ulSlotPhysAddr
선호됩니다. 포인터 형식과 정수 형식 간에 변환하기 위한 모든 새 Win64 도우미 함수 목록은 새 데이터 형식을 참조하세요.