본문 바로가기
Programming/윈도우 드라이버

Object Context란?

by 유주원 2013. 1. 4.

오브젝트 context는 드라이버가 오브젝트를 할당하고 배정할 수 있는 extra, nonpageable, memory 공간이다.


각각의 프레임워크 기반의 드라이버는 하나 또는 그 이상의 오브젝트 Context를 생성할 수 있다.

 

프레임워크 기반의 드라이버는 오브젝트 context 내에 오브젝트와 관련된 모든 데이터를 저장해야 한다.

 

예를 들어, USB 디바이스 드라이버는 자신의 프레임워크 디바이스 오브젝트를 위한 context를 생성한다. 드라이버는 디바이스의 USB_DEVICE_DESCRIPTOR, USB_CONFIGURATION_DESCRIPTOR 구조체 등과 같은 디바이스 정보들을 context 내에 저장한다.

프레임워크는 하나의 드라이버에서 또 다른 드라이버로 프레임워크 오브젝트를 전달하지 않기 때문에 두 개의 드라이버 사이에 데이터를 전달하기 위한 context를 사용할 수 없다.

 

오브젝트 context를 정의하기 위해선 먼저 하나 또는 그 이상의 구조체를 생성해야 한다. 각각의 구조체들은 분리된 context를 나타낸다. 드라이버는 생성된 context에 오브젝트 정보들을 저장할 것이다. 또한 드라이버는 프레임워크에게 각각의 구조체에 대한 접근자(accessor)를 생성하도록 요청해야 한다.

 

드라이버는 WdfDeviceCreate와 같은 함수를 사용하여 프레임워크 오브젝트를 생성할 때마다 선택적으로 context를 할당할 수 있다. 모든 오브젝트 생성 함수는 선택 사항으로 
WDF_OBJECT_ATTRIBUTES 구조체를 입력으로 생성할 수 있다. 이 구조체 속에는 프레임워크에게 오브젝트가 요구하는 메모리만큼 할당해 달라는 정보가 담겨져 있다.

 

드라이버는 오브젝트 생성 함수를 호출한 후에 WdfObjectAllocateContext 함수를 호출함으로써 추가적으로 context를 추가할 수 있다. WdfObjectAllocateContext는 오브젝트 생성 함수와 마찬가지로 WDF_OBJECT_ATTRIBUTES 구조체를 입력으로 받는다.

프레임워크가 Context를 할당할 때, 프레임워크는 context를 0으로 초기화한다.

프레임워크 또는 드라이버가 프레임워크 오브젝트를 지울 때, 프레임워크는 모든 오브젝트의 Context를 삭제한다.

 

만약 드라이버가 context 내에 버퍼 포인터를 저장한다면, 드라이버는 EvtCleanupCallback 함수를 사용하여 오브젝트가 제거될 때 버퍼를 해제해야 한다.

오브젝트의 context 구조체와 accessor 함수를 정의하기 위하여, 드라이버는 반드시 다음의 절차를 따라야 한다.

 

1. 저장하고자 하는 데이터를 기술하고 있는 구조체를 정의한다. 예를 들어 만약 디바이스
    오브젝트를 위한 Context를 생성하기를 원한다면, 드라이버는
 MY_DEVICE_CONTEXT라고
    불리는 구조체를 정의할 것이다.


2. WDF_DECLARE_CONTEXT_TYPE 매크로 또는
   WDF_DECLARE_CONTEXT_TYPE_WITH_NAME 매크로를 사용한다.


  - WDF_OBJECT_CONTEXT_TYPE_INFO 구조체를 생성하고 초기화 한다.

  - 드라이버가 후에 오브젝트의 Context에 접근하기 위해 사용할 accessor 함수를 정의한다.
     accessor 함수의 리턴 값은 
오브젝트의 context 포인터이다.

   

    WDF_DECLARE_CONTEXT_TYPE 매크로는 구조체의 이름으로부터 accessor 함수의 이름을
    생성한다. 예를 들어 만약 
context 구조체의 이름이 MY_DEVICE_CONTEXT라면 매크로는 
   WdfObjectGet_MY_DEVICE_CONTEXT라는 accessor 함수를 생성한다.

    WDF_DECLARE_CONTEXT_TYPE_WITH_NAME 매크로는 accessor 함수의 이름을 명시하게
    해 준다. 예를 들어 
디바이스  오브젝트의 context accessor 함수의 이름으로써 

   GetMyDeviceContext를 명시해야 한다.


3. 오브젝트의 WDF_OBJECT_ATTRIBUTES 구조체를 초기화하기 위하여 

   WDF_OBJECT_ATTRIBUTES_INIT을 호출한다.


4. WDF_OBJECT_ATTRIBUTES 구조체의 ContextTypeInfo   
   WDF_OBJECT_CONTEXT_TYPE_INFO 구조체의 주소로 설정하기 위하여 
   WDF_OBJECT_ATTRIBUTES_SET_CONTEXT_TYPE을 사용한다.


5. WdfDeviceCreate와 같은 오브젝트 생성 함수를 호출한다.

 

드라이버가 오브젝트를 생성한 후에 드라이버는 context를 추가하기 위해 
WdfObjectAllocateContext를 호출할 수 있다.

Step 1과 Step2에서는 전역 데이터 구조체를 정의하고 driver-callable routine을 생성하기 때문에, 반드시 전역 데이터가 선언된(대부분 헤더 파일) 드라이버 영역에서 이 단계를 완료해야 한다.

드라이버는 EvtDriverDeviceAdd Callback 함수와 같은 오브젝트를 생성하는 드라이버 루틴에서 3,4,5 단계를 마쳐야 한다.

 

프레임워크는 두 가지 타입의 오브젝트를 생성할 수 있다. 프레임워크 request 오브젝트와 프레임워크 파일 오브젝트이다.

드라이버는 각각의 오브젝트에 대해 WdfDeviceInitSetRequestAttributes 
WdfDeviceInitSetFileObjectConfig
 호출함으로써 오브젝트에 대한 context를 등록할 수 있다.


오브젝트가 생성된 후에 드라이버는 다음 절차에 따라 오브젝트의 context 포인터를 얻을 수 있다.


 - WDF_DECLARE_CONTEXT_TYPE 또는 WDF_DECLARE_CONTEXT_TYPE_WITH_NAME 
   매크로를 사용함으로써 accessor 함수를 호출한다.

 - 드라이버의 context 구조체의 이름을 입력받는 WdfObjectGetTypedContext를 호출한다.

   만약 드라이버가 context 포인터를 가지고 있다면, WdfObjectContextGetObject
   호출함으로써 context에 속해 있는 오브젝트를 찾을 수 있다.