Programming/Kernel / Driver2008. 12. 3. 11:54

WDM 드라이버 기본 구조

 

디바이스 드라이버 : 운영체제가 하드웨어 디바이스와 관련된 다양한 동작을 하기 위해 호출할 수 있는 서브루틴의 집합을 담을 수 있는 컨테이너의 개념.

 

디바이스 드라이버 계층화

 

WDM은 일정한 규격에 맞게 드라이버의 레이어가 생성되도록 한다.

DO(Device Object)들은 시스템이 소프트웨어의 하드웨어 관리를 돕기 위해 만들어 낸 자료 구조.

 

스택의 가장 낮은 레벨의 디바이스 객체는 PDO(Physical device object)라고 한다.

디바이스 객체의 가운데쯤 있는 것이 FDO(Functional device Object)라고 불리우는 객체이다.

 

FDO의 위쪽과 아래쪽에는 filter device object들의 모임이 존재할 것이다. FDO의 위에 위치한 객체는 상위필터(upper filter)라고 하고, 아래에 위치한 객체(PDO보다는 위에 있지만..)는 하위필터(lower filter)라고 한다.

 

Filter device object FiDO라는 약어로 사용하는 것을 볼 수 있지만 공식적인 것이 아니다. 하지만 FiDO라고 해도 알아듣도록 하자.

 

운영체제의 PnP 매니저 컴포넌트는 디바이스 드라이버의 요청에 의해 디바이스 객체의 스택을 형성한다.

 

Bus에 대한 드라이버의 역할 중에 하나는 bus에 부착된 디바이스를 나열하고, 그들 각각에 대한 PDO를 생성한다. PDO를 생성한 다음 PnP 매니저는 filter driver FDO를 찾기 위해 레지스트리 데이터베이스를 참고한다. 레지스트리 엔트리는 스택에 나타날 드라이버의 순서를 정한다. 그 결과 가장 낮은 레벨의 filter driver를 로딩하고 그것의 AddDevice 함수를 호출 함으로써 PnP가 시작된다.

AddDevice filter driver를 만들고 filter driver와 드라이버 사이의 수평 링크를 생성한다. 그리고 나서 PDO filter driver에 연결한다.

 

계층화의 목적.

디바이스에 영향을 주는 오퍼레이션에 대한 요청 각각은 IRP(I/O Request Packet)를 사용한다.

IRP는 디바이스에 대해 최상위에 위치한 드라이버로 정상적으로 보내지고, 다른 드라이버로 스택을 타고 내려올 수 있다. 각 레벨에서 드라이버는 IRP로 무엇을 할 것인가를 결정한다.

 

하나의 하드웨어를 위해 스택을 점유하고 있는 다양한 드라이버들은 각기 다른 역할을 수행한다.

FDO는 디바이스를 관리하고, bus driver(PDO)는 디바이스와 컴퓨터 사이의 연결을 관리한다.

Filter driver IRP의 스트림을 감시하거나 수정하는 역할을 한다.

 

PDO FDO와 완전히 다른 작업을 수행한다. FDO IRP PDO에게 내려보냄으로써 PDO에게 어떤 작업을 위임한다”.

 

시스템이 드라이버를 로드하는 방법

 

재귀적 계산(enumeration)

 

PnP 매니저는 실제로 존재하지 않는 루트(root)” 버스에 대한 빌트-(built-in, 내장)드라이버를 가지고 있다. PCI 같은 Primary hardware bus를 포함해서 루트 버스 드라이버는 레지스트리로부터 컴퓨터에 대한 정보를 얻는다.

 

Primary bus에 대한 function driver는 자신의 하드웨어를 전기적으로 나열(enumerate)한다.

PCI 버스는 각각의 부착된 디바이스에 대한 특별한 구성 공간(디바이스에 대한 디스크립션과 리소스 요구사항이 포함되어 있다)을 액세스하는 방법을 제공한다.

Bus driver가 하드웨어를 나열할 때 버스 드라이버는 일반적인 function driver로 가장하여 작동하다가 하드웨어를 감지한 후에는 드라이버의 역할이 바뀌게된다(감지된 하드웨어에 대한 새로운 PDO)를 생성하게 된다.

 

레지스트리의 역할

 

레지스트리 데이터베이스가 드라이버를 로드하고 디바이스를 구성하는 과정에서 결정적인 역할을 한다. 그러므로 어떤 레지스트리 키들이 관련되어 있고 그것들이 무엇을 담고 있는지 설명한다.

 

세가지 다른 레지스트리 키(하드웨어 키, 클래스 키, 서비스 키)들은 구성(configuration)과 관계가 있다. 저 세가지의 이름은 적절한 이름이 아니다.

하드웨어 키는 단일 디바이스에 대한 정보를 포함한다. (인스턴스 키라는 이름을 사용하기도 한다.)

클래스 키는 같은 타입의 모든 디바이스들과 관련이 된다.

서비스 키는 드라이버들에 대한 정보를 포함한다. (소프트웨어 키라는 이름을 사용하기도 한다.)

 

하드웨어 키 :

레지스트리의 HKEY_LOCAL_MACHINE\System\CurrentSet\Enum 서브키에서 나타난다.

Enum키 아래에 있는 첫번째 레벨에 위치한 서브키들은 시스템에 있는 다른 버스 나열자와 대응된다. 모든(과거 또는 현재) USB 디바이스들의 디스크립션이 …\Enum\USB 서브키안에 존재한다.

ClassGUID는 디바이스 클래스를 식별케 해주는 globally unique indentifier(GUID)의 고유 ASCII표현방식이며 디바이스의 클래스키에 대한 포인터이다.

Service서비스 키에 대한 포인터이다.

 

클래스 키:

HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Class에서 나타난다.

클래스 키들의 키 이름은 마이크로소프트에서 지정한 GUID이다.

각 디바이스는 클래스 키 아래에 자신의 서브키(0000 같은)를 가지고 있다. 이 키의 이름은 디바이스 하드웨어 키에 있는 드라이버 값이다.

 

서비스 키:

HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services에 나타난다.

이것은 드라이버의 실행 가능한 파일이 디스크에 놓인 위치를 나타내고 드라이버가 로드되는 방식을 제어하는 다른 매개 변수들을 포함한다.

서비스키에 대한 참고링크 : http://support.microsoft.com/kb/103000

 

 

드라이버 로딩의 순서

 

PnP 매니저가 새로운 디바이스를 접하게 되면 하드웨어와 클래스 키를 열고, 드라이버를 로드하기 위해 다음과 같은 순서로 작동한다.

1.     디바이스에 대한 하드웨어 키에서 지정된 하위 필터 드라이버. LowerFilters 값은 REG_MULTI_SZ 타입이기 때문에 하나 이상의 드라이버를 지정할 수 있다.

2.     클래스 키에서 지정된 하위 필터 드라이버, 또다시 하위 필터 드라이버, 이것들이 LowerFilter 값의 데이터 스트링에 나타난 순서대로 로드된다.

3.     하드웨어 키에서 Service 값에 의해 지정된 드라이버

4.     하드웨어 키에서 지정된 상위 필터 드라이버 그리고 UpperFilters 데이터 스트링에 나타난 순서

5.     마찬가지로 또다시 클래스 키에서 지정된 상위 필터 드라이버 그리고 UpperFilters 데이터 스트링에 나타난 순서대로 로딩한다.

 

시스템이 드라이버를 로드한다고 말할 때 이것은

드라이버의 이미지를 가상 메모리로 맵핑하고,

재배치 가능한 레퍼런스들을 수정하며,

드라이버의 메인 엔트리 포인트를 호출하는 것

을 의미한다. 메인 엔트리는 보통 DriverEntry라고 부른다.

 

디바이스 객체가 상호 관계를 가지는 방법

 

디바이스 객체 스택의 트리에서 IRP가 반드시 PDO에서 꼭대기의 filter driver object로 흘러가야 한다는 것을 의미하지 않는다. 간단하게 말하면 트리의 구조에 있는대로 다음의 드라이버객체로 IRP를 보낼 수도 있고 보내지 않을 수도 있다는 이야기이다.

 

이외에 설명이 더 있는데 이 부분은 잘 이해가 안된다.. L

 

 

드라이버 객체

 

I/O 매니저는 각각의 디바이스 드라이버를 나타내기 위해 드라이버 객체 자료 구조를 사용한다.

이 드라이버 객체 자료 구조는 부분적으로 불투명(opaque)하다. _DRIVER_OBJECT에서 강조되지 않은 부분이 그에 해당한다.

 

typedef struct _DRIVER_OBJECT{

   CSHORT Type;

   CSHORT Size;

   PDEVICE_OBJECT DeviceObject;

   ULONG Flags;

   PVOID DriverStart;

   ULONG DriverSize;

   PVOID DriverSection;

   PDRIVER_EXTENSION DriverExtension;

   UNICODE_STRING DriverName;

   PUNICODE_STRING HardwareDatabase;

   PFAST_IO_DISPATCH FastIoDispatch;

   PDRIVER_INITIALIZE DriverInit;

   PDRIVER_STARTIO DriverStartIo;

   PDRIVER_UNLOAD DriverUnload;

   PDRIVER_DISPATCH MajorFunction[IRP_MJ_MAXIMUM_FUNCTION + 1];

} DRIVER_OBJECT, *PDRIVER_OBJECT;

 

헤더는 구조체를 DRIVER_OBJECT라는 타입명으로 정의한다. 또한 포인터 타입(PDRIVER_OBJECT)을 선언하고 구조체 태그(_DRIVER_OBJECT)를 할당한다.

 

드라이버 객체 구조체의 액세스 가능한 필드들에 대해 간단하게 알아본다.

DeviceObject(PDEVICE_OBJECT) : 드라이버에 의해 관리되는 각각의 디바이스에 대한 디바이스 객체 자료 구조의 리스트를 가리킨다.

DriverExtension(PDRIVER_EXTENSION) : 오직 AddDevice(PDRIVER_ADD_DEVICE) 멤버만을 액세스 할 수 있는 작은 하위 구조체를 가리킨다. 그 안에서 드라이버가 드라이버 객체를 만들어 내는 함수에 대한 포인터이다.

HardwareDatabase(PUNICODE_STRING) : 디바이스에 대한 하드웨어 데이터베이스 레지스트리 키의 이름이 들어 있는 문자열을 나타낸다. \Registry\Machine\Hardware\Description\System과 같은 이름이다.

FastIoDispatch(PFAST_IO_DISPATCH) : 파일 시스템과 네트워크 드라이버가 익스포트(export)하는 함수 포인터들의 테이블을 가리킨다.

DriverStartIo(PDRIVER_STARTIO) : 직렬화(serialize) I/O 요청을 처리하는 드라이버 함수를 가리킨다.

DriverUnload(PDRIVER_UNLOAD) : 드라이버의 클린업 함수를 가리킨다.

MajorFunction(PDRIVER_DISPATCH의 배열) : I/O 요청 타입의 각각을 처리하는 드라이버의 함수에 대한 포인터들의 테이블이다.

 

디바이스 객체

 

다음은 DEVICE_OBJECT의 자료 구조이다.

 

typedef struct _DEVICE_OBJECT {
  CSHORT  Type;
  USHORT  Size;
  LONG  ReferenceCount;
  PDRIVER_OBJECT  DriverObject;
  PDEVICE_OBJECT  NextDevice;  PDEVICE_OBJECT  AttachedDevice;
  PIRP  CurrentIrp;
  PIO_TIMER  Timer;
  ULONG  Flags;
  ULONG  Characteristics;

  __volatile PVPB  Vpb;
 
PVOID  DeviceExtension;
  DEVICE_TYPE  DeviceType;
  CCHAR  StackSize;  union {
    LIST_ENTRY  ListEntry;
    WAIT_CONTEXT_BLOCK  Wcb;
  } Queue;
  ULONG  AlignmentRequirement;
  KDEVICE_QUEUE  DeviceQueue;
  KDPC  Dpc;
  ULONG  ActiveThreadCount;
  PSECURITY_DESCRIPTOR  SecurityDescriptor;
  KEVENT  DeviceLock;
  USHORT  SectorSize;
  USHORT  Spare1;
  PDEVOBJ_EXTENSION  DeviceObjectExtension;
  PVOID  Reserved;
} DEVICE_OBJECT, *PDEVICE_OBJECT;

 

DEVICE_OBJECT에 대한 자세한 내용 : http://msdn.microsoft.com/en-us/library/aa491677.aspx

 

출처 : http://wert.egloos.com/4502911

 

Posted by skensita