본문 바로가기

programming/WDM

WINDOW Driver 개발과정


Windows상에서 드라이버를 개발하는 방법을 알아보자. 다음과 같은 순서로
driver개발에 필요한 내용들을 살펴 보겠다.

1. 드라이버 개발을 위해 필요한 요소들
2. 드라이버 개발전에 고려할것들
3. 디버깅 과정
 
1) 컴파일러(compiler)
2) 링커(linker)
3) 에디터(Editor)
4) 헤더파일 및 라이브러리
4) 예제 및 기본 골격(Skeleton)
5) 디버거(Debugger) 등의 요소들이 드라이버를 개발하는있어서 필요한 기본적인 요소들이 된다.

이들은 각각 다음[표1-1 구성요소]와 같은 곳에서 구할수 있고 이를 기본으로 해서 드라이버를 개발하게 된다.
 
OS Win9x WinNT4.0 Win2000 XP 비고
Compiler VC++ VC++ VC++ VC++ or DDK  
Linker VC++ VC++ VC++ VC++ or DDK  
.h / .lib DDK DDK DDK DDK  
Skeleton DDK DDK DDK DDK  
Debugger DDK or SoftIce DDK or SoftIce DDK or SoftIce DDK or SoftIce  
Help DDK DDK DDK DDK  
[표1-1 구성요소]
DDK설치는 통상적으로 VC++을 먼저 설치하고 난후에 설치 하게 된다. 다른 예외는 다음을 참고하기바란다.

1) NT4.0의 경우는 VC++대신 SDK를 설치하고 난후 DDK를 설치해야 각종 path들이 바로 설정된다.
    단 DDK를 설치하고나면 DDK\bin\setenv.bat 파일이 생기고 이 파일에서 mstools 관련된 부분을
    주석 처리하면 VC++의 컴파일러(cl.exe)와 링커(link.exe)를 사용할수도 있다.

2) 9x 계열의 경우 DDK\bin\link.exe를 다른 이름으로 수정(rename)해서 VC++의 link.exe가 호-
    출되도록해야 정상적으로 link될수 있을수 있다.(DDK 버전에 따라 필요 없는 경우도 있다.)

3) XP의 경우는 DDK안에 컴파일러와 링커가 들어 있으므로 VC++등이 설치 되지 않아도 된다.
 
 
1) 대상 O/S는 무엇인가? :
개발하려는 OS에 따라 개발 방법이 달라질수 있다. 9x계열(windows95,windows98,ME)의 OS에서는 WDM이
지원하지 않는 드라이버를 Vxd라는 방식으로 개발 하였고 Windows NT 계열과는 호환되지 않는 드라이버이
므로 각각의 플랫폼 마다 드라이버를 따로 개발해야만 한다.
OS에 따라서 지원하지 않는 드라이버가 있을수 있다. 예를 들면 USB 의 경우 NT4.0에서는 USB bus 드라이버
를 지원하지 않으므로 WDM으로 개발되는 USB 드라이버들이 동작할수 없다.
또한 USB Mass Storage class를 지원하는 장치의 경우 ME나 2000,XP에서는 해당 드라이버를 OS가 가지고
있으나 Windosw98에서는 따로 드라이버를 개발해야 한다.
이외에도 OS의 특성에 따라 개발방법이나 범위가 많이 달라질수 있기 때문에 지원하려는 OS와 이의 특성에
관해서 먼저 살펴보아야 한다.
 
2) 개발하려는 드라이버는 드라이버 계층중 어디에 포함되는가?
드라이버는 많은 경우 특정 계층에 포함된다. 개발하려는 드라이버가 포함되는 계층에 따라 개발 방법이 달라진다.
 
3) 하드웨어적인 특성들은 무엇인가?
제어 하려는 하드웨어의 특성을 잘 파악해야한다. DMA를 사용하는지 버스 타입은 무엇인지, 인터럽트(inter-
rupt)나 IO방법등에 관해서 세심히 살펴보고 이를 이해해야한다.
 
4) 동기화(synchronizion)문제들이 발생할 요소는 무었인가?
사용하려는 어플리케이션이나 다른 드라이버와의 관계와 IO작업을 취소하거나 다른 IO를 시도할 때, 또는 장치가
예기치 않게 제거될 때 서로간에 동기화와 관련된 문제점들이 발생할만한 부분이 없는지, 있다면 어떻게 이를 극복
해야 하는지 먼저 계획해야 한다.
 
5) 디버깅 및 유지 보수는 어떻게 할것인가?
많은 고급기법들을 사용하는 것이 반듯이 좋은 프로그램은 아니다. 추후의 디버깅이나 유지보수에 걸림돌이
될만한 개발 방법이나 설계는 없는지 생각해 보고 가능하면 OS에서 제공하는 방법들을 사용해서 드라이버를
개발할수 있게 하자.
 
6) 어플리케이션과는 어떻게 데이터를 주고 받을 것인가?
어플리케이션과 상호 통신하는 부분도 세심한 주의가 필요하다. 버퍼사용법과
 
7) I/O 속도에 있어서 문제될 부분은 없는가?
하드웨어 스팩에서 언급하는 IO속도가 반듯이 그대로 유지되지는 않는다. 또한 같은 버스를 사용하는
하드웨어라고 하더라도 IO 방법에 따라 속도차이가 많이 날수 있다.
 
8) 해당 기능들을 사용할때 IRQL은 문제가 발생하지 않는가?
드라이버의 모든 함수들은 IRQL이라는 특별한 레벨에서 실행되고 모든 함수들은 사용될수 있는 IRQL이
명시 되어 있다. 구현하려는 기능이 해당 IRQL에서 동작하는지 잘 검토해야 한다.
 
 
3절에서 소개되는 내용들은 설치된 OS나 DDK 버전에 따라 내용상 약간의 변동이 있을수 있다. 하지만
큰 흐름상의 변화는 없으므로 다음 내용들을 참고하기 바란다.

1) 빌드 방법
   
   1.1 DDK를 설치한다.
   1.2 DDK버전이나 O/S에 따라 약간의 차이는 있겠지만 다음[그림3-1 개발환경]과 같이 Cheked Build-
         Environment나 Free Build Environment 를 연다.
 
[그림3-1 개발환경]
   1.3 소스가 있는 디렉토리로 이동한다.
   1.4 Build.exe로 드라이버를 빌드한다. ?ewc는 build.exe의 빌드 옵션으로 build /? 라고 입력하면
       세부빌드 옵션을 확인할수 있다. 이때 -ewc등의 옵션은 대소문자에 따라 다른 의미를 가지므로
       정확히 사용해야 한다.
 
드라이버를 생성할 때 사용하는 build.exe는 DDK 안에 포함되어 있는 유틸리티 프로그램으로 sources라는
파일을 참조해서 드라이버를 생성한다.

그럼 DDK에서 제공하는 가장 단순한 드라이버인 portio를 가지고 드라이버를 생성하고 설치하는 과정을 살펴보자.
지금부터 사용할 예제는 DDK를 설치하고 다음의 폴더에서 찾아 볼수 있다.

WINDDK\src\general\portio
WINDDK\src\general\portio\sys 폴더안에는 드라이버 소스가 들어 있다.
WINDDK\src\general\portio\gpdread 폴더안에는 위의 드라이버를 이용해서 특정 포트(port)에서 값을
읽어 오는 프로그램의 소스가 들어 있다.
WINDDK\src\general\portio\gpdread 폴더안에는 위의 드라이버를 이용해서 특정 포트(port)에 값을
적는 프로그램의 소스가 들어 있다.


우선 sys 폴더를 살펴보자. 해당 폴더에 있는 파일들은 각각 다음과 같은 내용들을 담고 있다.

genport.c : 드라이버를 구성하고 있는 모든 코드들이 들어 있다.
GENPORT.H : 함수선언과 몇가지 메크로(macro)가 들어 있다.
GENPORT.RC : 드라이버의 리소스(resource)가 들어 있다.
MAKEFILE : 표준 메이크 파일로 nmake.exe가 참조하는 파일이다.
SOURCES : build.exe가 참조하는 파일로 생성될 드라이버의
이름을 비롯해서 드라이 빌드와 관련된 내용들이 서술되어 있다.

드라이버를 빌드할 때 직접 참조하는 파일인 SOURCES파일은 다음과 같은 내용이 포함되어 있다.
SOURCES파일에서 주석은 “#”을 사용한다.

 
ARGETNAME=genport #genport.sys라는 이름으로 드라이버를 생성하라.

TARGETPATH=obj#”objType_Version_Cpu\<cpu_type>” 폴더에 컴파일된 .obj 파일들을 위치 시키라.
    Intel x86 cpu의 경우 <cpu_type>는 i386이 된다.

TARGETTYPE=DRIVER#생성되는 파일은 드라이버이다. NTSTATUS DriverEntry(IN PDRIVER_OBJECT
    DriverObject,IN PUNICODE_STRING RegistryPath)함수를 entry point로 설정해서 커널이 위치한 곳에서
    동작하는 모듈로 컴파일 및 링크를 실행하라.

INCLUDES=..\#상위 폴더를 include path에 추가하라.

TARGETLIBS= $(DDK_LIB_PATH)\wdmsec.lib# wdmsec.lib를 링크되는 라이브러리에 추가하라.

SOURCES=genport.c genport.rc #genport.c와 genport.rc 두 파일을 컴파일 및 링크하라.
 
2) 설치 방법(windows2000)
 
2-1. 제어판의 “하드웨어 추가 제거”를 더블클릭한다.
 
2-2. “다음”을 클릭한다.
 
2-3 “장치 추가 / 문제 해결”을 선택하고 “다음”을 클릭한다.
 
2-4 “새 장치추가”를 선택하고 “다음”을 클릭한다.
 
2-5 “아니오, 목록에서 하드웨어를 선택합니다”를 선택하고 “다음”을 클릭한다.
 
2-6 “기타장치”를 선택하고 “다음”을 클릭한다.
 
2-7 “디스크 있음” 선택하고 genport.inf 파일을 찾아서 선택해 준다.
 
2-8 적당한 리소스를 선택하고 다음을 누른다.
 
2-9 마침을 눌러서 설치를 완료한다.
 
3. 디버깅 과정
1) 사용 가능한 KernelMode Debugger

   1-1 SoftIce
   1-2 WinDbg


2) Memory leak 검사

   2-1 ExAllocatePool()등의 함수는 반듯이 ExFreePool()등의 함수를 호출하는지 확인
   2-2 Irp나 기타 UnicodeString 같은 자료구조들의 해제검사
   2-3 bound ckecker와 같은 툴의 도움을 얻어 메모리관련문제들이 없는지 확인한다.


3) 문제 발생시 check point

   3-1 하드웨어적인 결함은 없는가?
   3-2 메모리 누수는 없는가?
   3-3 메모리나 자료구조들을 참조할때 Assert등으로 충분히 검사하고 있는가?
   3-4 Crashl Dump파일 분석
   3-5 세세한 부분까지 디버거로 확인했는가?
   3-6 새롭게 추가된 모듈은 충분히 검증되었는가?
   3-7 사용하는 함수들은 적절한 IRQL에서 사용되고 있는가?



이상으로 드라이버 개발에 관한 전반적인 내용들을 살펴 보았다. 처음 드라이버를 개발하시려는 분들에게
부디 도움이 되기를 바라며 각항목들의 구체적인 내용들은 DriverOnline의 여러 강좌와 QnA를 통해 여러-
분들의 지식으로 만들어가기를 바란다.