'Programming'에 해당되는 글 100건

  1. 2008.12.05 WDK 다운로드
  2. 2008.12.03 드라이버 로딩
  3. 2008.12.03 WDF란..
  4. 2008.12.03 AJAX란?
  5. 2008.12.03 XAML이란?
  6. 2008.12.03 XML이란
  7. 2008.12.03 WDM 드라이버의 기본 구조
  8. 2008.12.03 드라이버 프로젝트 시작하기
  9. 2008.12.03 Windows Driver Model(WDM)의 전반적인 이해
  10. 2008.12.03 WDM과 WDF
Programming/Kernel / Driver2008. 12. 5. 13:00
WDK 란 Windows Driver Kit 의 약자로서, WDM 을 개발하기 위한 도구입니다.
즉, WDK 를 설치해야 windows device driver 를 개발할 수 있습니다.
WDK 이전 버전으로는 DDK (Device Driver Kit) 라는게 있습니다.
DDK 는 아래 사이트에서 간단히 다운로드 받을 수 있습니다.
http://www.microsoft.com/whdc/DevTools/ddk/default.mspx

우리는 WDM 을 개발할 것이므로 WDK 를 설치하겠습니다.
WDK 다운로드는 아래 과정을 참고하세요.

1. https://connect.microsoft.com/directory/ 에 접속합니다.



2. 화면 우측 상단의 '로그인' 을 클릭한 후, Microsoft Live ID 를 이용하여 로그인 합니다.
보통은 MSN 아이디로 로그인 하면 되나, 아이디가 없는 경우 '지금 등록' 버튼을 눌러서 등록한 후 로그인하면 됩니다.



3. 로그인을 한 후, 연결 디렉터리 ( https://connect.microsoft.com/directory/ ) 페이지에서
ctrl + f 를 눌러 wdk 를 입력합니다. 즉, 해당 웹페이지에서 wdk 가 있는 부분을 찾습니다.



4. Windows Driver Kit (WDK), Windows Logo Kit (WLK) and Windows Driver Framework (WDF) 에 있는 '지금 신청' 을 클릭합니다.

5. '등록 정보 입력' 화면에서 '계속' 을 클릭합니다.

6. '사용 약관' 화면에서 '동의함' 을 클릭합니다.

7. '등록' 화면에 정보를 입력합니다.
내 이름, 위치/국가, 내 전자 메일 주소 등을 입력한 후, '계속' 을 클릭합니다.
위치/국가는 '대한민국'을 선택합니다.

8. '전자 메일 주소 소유자 확인' 화면에서 '계속' 을 누릅니다.

9. 'Connect에 오신 것을 환영합니다!' 화면에서 닉네임을 입력하고 '계속' 을 클릭합니다.

10. 그럼 아래와 같이 'Windows Driver Kit (WDK), Windows Logo Kit (WLK) and Windows Driver Framework (WDF) 홈' 페이지가 나옵니다.



11. 왼쪽 메뉴에서 '다운로드'를 클릭합니다.

12. 'WDK SP1 for Windows Server 2008 SP1' 을 클릭합니다.

13. '단일 파일 다운로드' 아래에 있는 '다운로드'를 클릭해서 다운로드 받으세요.



보시다 시피 WDK 를 다운로드 받는 과정이 상당히 번거롭습니다.


출처 : http://seoz.egloos.com/1833736
Posted by skensita
Programming/Kernel / Driver2008. 12. 3. 15:24

드라이버를 개발할 때 필요한 유틸리티 중에 하나가 바로 InstDrv.exe 라는 녀석입니다. 개발된 드라이버를 테스트 해볼 때 INI파일 없이 간단하게 드라이버를 설치하고 실행해볼수 있도록 해주는 유틸입니다.

  

사용자 삽입 이미지

위의 경로에 전체경로를 적어주고 Install 버튼을 누르면 드라이버가 설치가 되고 Start를 누르면 드라이버가 로딩이 됩니다. (DriverEntry 호출되는 시점이 여기입니다. ^^)

참 편리한 프로그램인데 한가지 불편한 점은 전체경로를 적는 것입니다. 요즘 같은 환경에 누가 전체경로를 타이핑하고 있나~ 라는 생각에 이 프로그램에 파일다이얼로그를 추가해서 마우스 클릭으로 파일을 선택할수 있도록 해보자는 생각으로 아래처럼 만들어 봤습니다.
 

사용자 삽입 이미지

 

기능은 똑같구요 에디트 옆에 버튼을 하나 두어서 파일다이얼로그를 띄어서 드라이버 파일을 선택할수 있도록 하였습니다. ^^  원래 유틸은 파일 크기가 30KB인데 파일다이얼로그와 about 창이 추가되어서 44KB로 크기가 조금 늘었습니다. 이정도야 조금 편리해 지는데 따른 coast 치고는 싼편이죠.. 이것말고도 프로그램 개발하는데 들어간 시간이 있었지만요.. ㅋ

앞으로 파일 전체 경로를 쓰는 번거로움이 조금 사라지면 개발시간은 충분히 보상되리라 생각됩니다. (반나절 정도 걸렸네요 ^^)

 

드라이버 개발시에 유용한 Device Tree라는 도구도 있습니다. 현재 컴퓨터에 로딩되어 있는 드라이버들의 목록을 보여주는 것인데, DDK를 설치하면 그안에 포함되어 있습니다.


사용자 삽입 이미지
 

 

새로 만든 InstDriver.exe를 가지고 드라이버 로딩 테스트를 하니까 위의 Device Tree에서 잘 보입니다.

 

참고로 드라이버를 설치하고 실행시키는 방법을 코드로 작성시에는 SCManager(스컴매니져)를 이용하여 서비스로 드라이버를 실행시켜주는 방법을 사용하였습니다. OpenSCManager(), OpenService(), StartService(), ControlService(), DeleteService() 등의 함수를 사용하였습니다.

 

두개의 파일을 모두 올려봅니다.


Posted by skensita
Programming/Kernel / Driver2008. 12. 3. 15:19
제가 자주 방문하는 사이트에서 WDF에 대해서 좋은 글이 있어서 올려 놓습니다.

사이트 주소는 www.insidekernel.net 입니다. 참고로 이 사이트 주인장 레벨이 초고수 이십니다. ^^


첫번째 순서로 아키텍쳐나 WDF 드라이버를 실제로 제작해보기에 앞서 WDF가 무엇인지 간략히 살펴보는 시간을 갖도록 합니다. 참고로 이 글은 whitepaper 중 ‘WDF Introduction’이란 문서를 번역한 것입니다. 인터넷의 다른 WDF 소개글과 중복되는 내용이 있으나, 이후의 강좌글에 대한 이해와 일관성을 위하여 우선적으로 첫번째 강좌글로서 소개합니다.
현재의 기술 - WDM 이란?

윈도우는 현재 디바이스 드라이버 개발을 위해 ‘WDM(Windows Driver Model)’이라는 모델을 지원하고 있습니다. 그리고 작성하려는 특정한 디바이스 종류에 따라서 device-class specific한 드라이버 모델을 따로 가지고 있기도 합니다. 구체적으로 나열하자면, WDM은 비동기 I/O(asynchronous I/O), 드라이버 레이어링, plug and play, power management, WMI 같은 것들을 포함하고 있습니다.

device-class specific driver model은 크게 두 종류로 구분할 수 있습니다.

클래스 드라이버 = 포트 드라이버(MS가 제작) + 미니포트 드라이버(하드웨어 벤더가 제작)

  • 포트 드라이버는 디바이스 클래스에 필요한 많은 작업을 함.
    미니포트 드라이버는 드라이버 specific한 것을 지원.

예를 들어보자면, MS가 제공하는 SCSI 포트 드라이버는 SCSI 디바이스를 위한 기본적인 요구사항들을 처리하고, SCSI 미니포트 드라이버는 디바이스 specific한 작업들을 지원합니다.

윈도우가 새로운 디바이스 클래스들을 추가로 지원하면서, 미니포트 모델도 늘어났고, 현재 윈도우는 열개가 넘는 미니포트 모델을 지원하고 있습니다.
WDM의 한계
1. WDM 드라이버를 작성하는 것은 로우레벨 작업이고 또한 매우 복잡하다.

예를 들어서, 현재의 WDM 모델에서 드라이버를 작성할 때 plug and play와 power management를 지원하려면 최소한 2000 라인이 필요합니다. 또한 power management, pnp, 동기화, 비동기 i/o 를 쓰기위한 DDI(device driver interface)역시 무척 쓰기가 어렵습니다. 완벽한 pnp 와 power management state 엔진을 구현하기 위해선 최소 100가지 state를 지원해야 합니다.
2. DDI가 구식이다

DDI가 처음 디자인 될 때에는 지금과는 상황이 많이 달랐기 때문에, 현재의 요구사항과는 좀 차이가 있습니다. 몇년전 처음으로 DDI를 디자인 할 때에는, MS는 써드파티 드라이버 개발 업체를 참여시키지 않았다고 합니다. 그래서 DDI는 커널로부터 곧바로 export 되었으며, 오직 퍼포먼스 만을 위해 디자인되었고, 보안이나 사용의 편의성 같은건 고려되지 않았습니다. 그리하여 DDI는 드라이버들에게 운영체제의 핵심적인 데이터 구조들을 곧바로 노출하고, 결과적으로 MS는 이런 구조체들의 변경이 제한될 수 밖에 없었고, 드라이버가 시스템을 크래쉬 시킬 확률도 높아진 것입니다.

또한 Versioning 지원이 없어서, 윈도우의 버전이 달라지면 드라이버도 다른 바이너리를 사용해야 하거나, 가장 오래된 윈도우 버전에서 사용가능한 기능만을 써서 만들어야 했습니다.

3. 미니포트 모델이 너무 많다.

윈도우는 현재 열개 이상의 미니포트 모델을 지원하고 있습니다. 미니포트 모델마다 pnp와 power management를 다루는 방법이 다릅니다. 미니포트 인터페이스는 운영체제에 새로운 기능이 추가될 때라던가, 새로운 하드웨어 기술이 나올때마다 새로 업데이트 되어야 합니다. 결과적으로, 미니포트 인터페이스는 자주 옛날 기술이 됩니다.

4. 멀티펑션 디바이스를 지원하는 작업은 너무 복잡하다.

두가지의 다른 미니포트 모델에 적용되는 멀티펑션 디바이스를 지원하기 위해서, 개발자는 WDM 버스 드라이버와 두개의 미니포트 드라이버 작성이 필요합니다.

5. 현재 드라이버 모델은 커널 레벨에서만 동작해야 한다.

WDM과 미니포트 드라이버 모델은 커널모드에서 실행되고, 커널 모드 드라이버는 운영체제의 일부로 대접받게 되므로, 시스템의 가상 메모리 영역에 접근권한을 가지고 있습니다. 그래서 커널 모드 드라이버에서 에러가 발생하면 바로 시스템을 크래쉬 시키는 BSOD를 겪게 되지요.

오늘날의 많은 디바이스들은 인터럽트나, 엄격하고 긴급한 타이밍 관리나, 하드웨어 레지스터를 직접 건드릴 일도 없습니다. 이런 드라이버들은 유저모드에서 동작해도 충분합니다.

6. 테스트 툴들이 쓰기 어렵다

새로운 정적 분석 툴인 PREfast와 static drive verifier는 드라이버 퀄리티를 아주 크게 향상시킬 수 있습니다. 이런 툴들은 룰집합에 따라 코드를 검사합니다.


차세대 윈도우즈 드라이버 모델의 디자인 목적

1. 드라이버 모델은 심플하고 유연성(flexible)이 있어야 한다

심플하고 플렉서블한 드라이버 모델은 쉽게 빠르게 견고하고 믿을 수 있는 드라이버를 생산하는데 도움을 줍니다.

2. 드라이버 모델은 코어 운영 체제 컴포넌트와 분리되어야만 한다.

드라이버 모델은 운영 체제의 세세한 부분과는 별도로 구분되어 별도의 프레임웍으로 구성되어야 합니다. 이렇게 함으로써 MS는 드라이버와의 호환성에 대한 걱정없이 운영체제를 업데이트 할 수 있을 것이고, 운영 체제의 새 버전이 나와도 드라이버 개발자들이나 하드웨어 벤더들이 이에 영향없이 일을 할 수 있을 것입니다.

3. 드라이버 모델은 일관성이 있어야 한다.

드라이버 모델은 모든 디바이스 클래스 들에 대해서 일관성이 있어야 합니다. 모든 디바이스들이 반드시 지원해야 하는 PnP나 Power Management, 동기화, I/O 큐, 레지스트리 엑세스, DMA 지원같은 운영 체제를 위한 핵심 기능들이 모든 디바이스 종류에 구애받지 않고 일관성 있게 개발자들에게 제공되어야 합니다. 그렇게 되면 개발자가 새로운 디바이스에 대한 드라이버를 작성할 때에도 진입장벽을 낮게 가져갈 수 있을 것입니다.

4. 드라이버 모델은 확장성이 있어야 한다.
5. 드라이버 모델은 유저모드를 지원해야 한다.

유저모드 드라이버는 시스템의 안정성을 크게 높일 것입니다.

6. 드라이버 모델은 고급 레벨의 언어를 지원해야 한다.

객체 지향과 type-safe 를 지원하는 언어로 작성하면 코드 분석 툴에 큰 도움이 됩니다.

WDF (Windows Driver Framework)

WDF는 다음 컴포넌트들을 포함합니다.

  • 커널모드 드라이버 프레임웍.
    유저모드 드라이버 프레임웍
    드라이버 검증 툴

WDF는 객체 지향, 이벤트 드리븐(event-driven) 모델을 제공합니다!

WDF의 Object들은 블럭 쌓기처럼 동작합니다. 드라이버는 이들 object들을 잘 정의된 인터페이스를 통해서 수정합니다.

특정 이벤트들은 지정된 object의 타입에만 영향을 미칠 수 있습니다. 프레임웍은 각 이벤트에 대한 기본 동작을 정의합니다. Device specific 한 행동을 정의하기 위해서, 드라이버는 기본 핸들러를 오버라이딩 하는 콜백 루틴을 포함합니다.  (즉, 프레임웍에 의해서 디바이스 드라이버에 필요한 수많은 기본 핸들러들이 기본으로 제공이 되며, 개발자들은 자신에게 필요한 이벤트만 C++에서의 상속과 같이 오버라이딩을 하여 구현하면 됩니다)

MS는 WDM과 NDIS와 같이 기존의 미니포트 모델 드라이버 지원을 계속할 것입니다.

1. 커널 모드 드라이버 프레임웍(Kernel-Mode Driver Framework)

커널모드 드라이버 프레임웍(KMDF)은 커널모드 드라이버를 만드는데 필요한 기본적인 기능인 PnP, Power Management, I/O 큐, DMA, WMI 그리고 synchronization 같은 기본적인 기능들을 구현하고, IEEE 1394, USB 같은 주요 버스들에 대한 지원도 합니다.

커널모드 드라이버 프레임웍은 운영체제 커널의 일부분으로 포함된 것이 아니라, 별도로 제공되는 독립된 라이브러리입니다.

커널모드 드라이버 프레임웍을 사용하면 멀티펑션 디바이스를 지원하는 버스 드라이버를 작성하는 것이 현재의 WDM 모델을 사용해서 하는 것보다 훨씬 간단해집니다. 위와 같은 상황에서 드라이버는 그 자신의 자식 디바이스들을 enum하여 각 자식 디바이스들의 프로퍼티들을 리스트 합니다. 이때 KMDF의 프레임웍은 device object 셋팅, 자식 디바이스들을 위한 드라이버에게 IRP 보내기, 등과 같은 기본적이고 공통된 요구사항들을 대신 처리합니다. 이와 관련된 내용은 KMDF는 샘플 토스터 버스 드라이버를 참고하시면 됩니다.

커널모드 드라이버 프레임웍에서 인터페이스는 미래에도 가능한 한 드라이버의 독립성을 추구하도록 디자인 되었습니다. 만약 드라이버가 크래쉬되면, 운영체제는 시스템을 멈추거나 전체를 크래쉬하지 않고 복구하거나 드라이버에 의해 할당된 리소스들을 클린업 합니다. 이러한 드라이버의 독립성을 구현하기 위해서는 인터페이스가 잘 디자인 되어야 합니다.

그리고 WinUSB, ultrawide 밴드, HD Audio, 그리고 다른 여러 다른 디바이스 타입들이 비스타를 위한 KMDF 드라이버로 계획되어 있습니다.
2. 유저 모드 드라이버 프레임웍 (User-Mode Driver Framework)

유저모드 드라이버 프레임웍(UMDF)은 PnP, Power Management, 비동기 I/O 지원을 포함하는 커널모드 프레임웍 기능의 일부분을 구현하고 있습니다. DMA 수행, 인터럽트 지원, nonpaged 풀 같은 커널모드 리소르를 사용하지 않는 드라이버들이라면 유저모드에서 실행될 수 있습니다.

유저모드 프레임웍을 사용하면 개발자들은 네트워크와 연결된 디바이스들(network-connected devices)을 위한 드라이버와 PMP, 카메라, 셀폰 같은 USB 디바이스들을 위한 드라이버를 만들 수 있습니다. 비록 이들 드라이버들이 유저모드에서 실행되지만, 그것들은 커널모드 PnP 드라이버들과 동일한 방법으로 시스템이 찾고 설치하는 표준 PnP 드라이버입니다.

유저모드 드라이버 프레임웍은 비스타에서 지원될 것입니다. XP에서의 UMDF지원은 정책결정 중입니다.

3. 드라이버 검증 툴들(Driver Verification Tools)

두개의 룰 기반 정적 분석 툴인 PREfast와 Static Driver Verifier(SDV)가 커널모드 드라이버/유저모드 드라이버 프레임웍 모두를 지원할 것입니다.

PREfast는 드라이버가 지켜야만 하는 규칙들을 검사합니다.

PREfast는 드라이버의 코드가 어떻게 어떤 함수들을 호출하는지를 룰에 따라 분석합니다. 예를 들어서, 함수A가 스핀락을 얻고나서 PASSIVE_LEVEL에서 실행되어야만 하는 Z 함수를 호출하려고 했을때, PREfast는 스핀락을 얻어서 IRQL이 DISPATCH_LEVEL로 올라갔다고 이 에러를 표시해줄겁니다. 그러나, 만약 함수 A가 스핀락을 얻고, DISPATCH_LEVEL에서 호출되도 되는 함수 M을 호출했는데 함수 M이 함수 Z를 호출하려고 했다면, PREfast는 이런 에러는 못 잡아냅니다. PREfast는 Windows Server 2003 SP1 DDK에서 얻을 수 있고, 이후 버전은 WHDC 웹사이트에 올아올 겁니다.

SDV
SDV는 룰 기반의 툴로서, 윈도우 내부와 어떻게 드라이버가 운영 체제 내부의 인터페이스들을 사용해야 하는지에 대해 지식을 가지고 있습니다. DriverEntry를 호출하고 차례로 AddDevice를 호출하는 것처럼 운영체제의 호출을 에뮬레이팅 합니다.


출처 : www.insidekernel.net

Posted by skensita
Programming/WEB2008. 12. 3. 15:17

ASP.NET AJAX란 Microsoft에서 만든 AJAX 프레임워크로서 ASP.NET 기반의 AJAX 프로그래밍을 쉽게 구현하도록 지원한다. ASP.NET AJAX는 서버로 페이지 업데이트를 위한 라운드 트립의 요청 없이, 브라우저에서 웹 응용프로그램의 페이지의 의미 있는 중요한 부분만 실행할 수 있도록 하는데 그 목적이 있다. 이는 AJAX가 지향하는 부분과 동일하며, ASP.NET을 이용하여 이를 쉽게 적용하고 결과물을 얻을 수 있는 것이다.

ASP.NET AJAX 개발 기술은 ASP.NET 2.0 서버 기반의 개발 플랫폼의 ECMAScript(Javascript) 클라이언트 라이브러리로 통합되어 있다. ASP.NET AJAX는 클라이언트 스크립트에서 웹 기반 응용 프로그램을 호출하고자 하는 AJAX의 전략을 기본으로 하여 만들어진 프레임워크로 볼 수 있는 것이다.

왜 ASP.NET AJAX를 사용하는가?
ASP.NET AJAX를 이용한 개발은 전형적인 웹 응용 프로그램에 가지고 있는 한계를 극복한 AJAX 스타일의 새로운 웹 응용 프로그램을 개발할 수 있도록 지원한다. AJAX 스타일의 응용 프로그램은 다음의 장점을 가진다.
 
       ● 향상된 성능
       ● 사용자 인터페이스의 확대
       ● 웹 페이지의 부분 업데이트
       ● 비동기 포스트백
       ● 브라우저 독립성

ASP.NET AJAX 목표
ASP.NET AJAX의 목표는 응용 프로그램 제작에 있어 다양한 선택을 주기 위함이 가장 크다. ASP.NET AJAX를 사용하는 것으로만 개발자들은 ASP.NET AJAX 응용 프로그램을 제작하는데 도움을 받을 수 있고, 서버상의 ASP.NET의 특징과 ASP.NET AJAX 클라이언트 스크립트의 특징이 통합된 모델을 이용하여 개발할 수 있게 되는 것이다.


■ 클라이언트 스크립트를 이용하여 AJAX 스타일 응용 프로그램 작성
AJAX 기반의 개발은 생각보다 상당히 복잡하다. 자바스크립트가 기본으로 이용되며, 브라우저 별로 각기 다른 자바스크립트를 모두 고려하여 코드를 만들어야 하기 때문이다. 그러나 ASP.NET AJAX를 이용하면 이런 복잡한 AJAX 구현에 다음과 같은 도움을 얻을 수 있다.
 
● 일관성. 자바스크립트에서의 개발을 위한 객체지향 기반의 API 집합
● 클라이언트 스크립트를 위한 타입 제어
● 자동 브라우저 안정성. 여러 브라우저에서 실행되지만 브라우저에 따른 추가 작업이 필요 없음
● 리치 UI 특징을 지원하는 클라이언트 스크립트 API와 컴포넌트를 사용. AJAX 스타일의 응용프로그램에서 일반적으로 요구되는 확장된 코드로 작성된 여러 가지 컴포넌트를 쉽게 이용할 수 있다. 예를 들어, 드래그 앤 드롭, 자동 채우기와 같은 기능들이 있다.
● ASP.NET 서버 컨트롤을 위한 선언적인 문법과 유사한 클라이언트 개발을 위한 선언적인 스크립트 모델을 사용. 이를 사용하면 복잡한 코딩작업을 줄이거나 삭제할 수 있다.
 
ASP.NET에 통합되는 클라이언트 스크립트
ASP.NET AJAX의 또 다른 목적은 ASP.NET 서버 사이드 개발과 함께 클라이언트 스크립팅을 통합하는데 있다. 대부분의 개발이 클라이언트 또는 서버 중 하나에 집중되어 있는데 반해 ASP.NET AJAX는 개발자들이 사용하기 편한 방식을 이용하여 응용 프로그램을 제어할 수 있도록 클라이언트/서버 모두를 위한 툴을 모두 지원한다. ASP.NET은 ASP.NET AJAX 응용 프로그램을 위해 다음의 서버 사이드 특징을 지원한다.
 
● 프로파일 서비스처럼 ASP.NET AJAX 응용 프로그램의 통합에 유용한 웹 서비스
● ASP.NET AJAX 응용 프로그램에 필요한 클라이언트 스크립트를 출력해주는 ASP.NET 웹 서버 컨트롤. 이 컨트롤들은 ASP.NET AJAX 클라이언트 스크립트 API와 컴포넌트를 학습을 줄여주는데 도움을 준다.
● Visual Studio와 같은 툴과의 통합 지원. 디자인 타임 개발 환경, 디버깅, 구문 실행, 관리 및 생산성 향상을 위한 특징들을 제공한다.
 
ASP.NET AJAX 아키텍처
ASP.NET AJAX 응용 프로그램은 웹 서버상의 서비스 또는 응용 프로그램을 호출하는 ASP.NET AJAX 클라이언트 스크립트 라이브러리를 사용하는 웹 응용 프로그램으로 이루어진다. 그러나 보다 향상된 개발 모델을 위해서는 ASP.NET AJAX 서버 컴포넌트도 사용할 수 있다. 그러므로 ASP.NET AJAX는 클라이언트 스크립트 라이브러리와 서버 컴포넌트의 양쪽 모두를 포함한 아키텍처를 가진다고 이야기할 수 있다.

■  ASP.NET AJAX 클라이언트 컴포넌트
ASP.NET AJAX 클라이언트 스크립트 라이브러리는 객체지향 개발을 위한 특징을 제공하는 여러 가지 자바스크립트(.js) 파일로 구성된다. 이들은 이전의 스크립팅 개발 환경에서는 지원되지 않았던 모델로, ASP.NET AJAX에서 고유한 기능을 지원하기 위해 클라이언트로 제공되는 자바스크립트 파일들의 집합으로 이해할 수 있다. 다음의 몇 가지 기능들이 이들 스크립트에서 제공되는 것이다.

● 브라우저 호환성. 여러분들이 개발하는 ASP.NET AJAX 스크립트를 위한 대부분의 브라우저에서 동일 코드를 이용하여 동작하도록 브라우저 호환성을 지원.
● 클래스, 네임스페이스, 이벤트 핸들링, 상속, 데이터 타입, 직렬화와 같은 자바스크립트를 확장할 수 있는 코어 서비스들.
● 스트링 빌더(String Builder), 에러 핸들링과 같은 컴포넌트를 가지는 ASP.NET AJAX 기반의 클래스 라이브러리.
● 웹 기반 서비스와 응용 프로그램과 통신을 제어하고 비동기 원격 메서드 호출을 관리하는 네트워크 레이어.
● 실행, ASP.NET AJAX 선언적인 문법, UI 컴포넌트, 데이터 바인딩과 같은 ASP.NET AJAX 클라이언트 UI 레이어.
● 클라이언트 개발을 위한 ASP.NET AJAX 특정 컨트롤을 작성할 수 있는 컨트롤 레이어. 이들 컨트롤들은 데이터 바운드, 스크립트, ASP.NET AJAX 메서드에 바인딩 될 수 있다. 자동 채움 텍스트 박스, 일반적인 폼 컨트롤, 데이터 바운드 listview 컨트롤, 네비게이션 컨트롤들이 이에 해당한다.

■  ASP.NET AJAX 서버 컴포넌트
ASP.NET AJAX 서버 컴포넌트는 ASP.NET 웹 서비스와 ASP.NET 서버 컨트롤로 이루어진다. 모든 ASP.NET의 특징은 ASP.NET AJAX 응용 프로그램에서 사용 가능하다. ASP.NET AJAX 또한 웹 서비스와 서버 컨트롤의 ASP.NET에서의 컴포넌트를 포함한다. 이들 컴포넌트들은 ASP.NET AJAX 클라이언트 스크립트 라이브러리와 결합하여 동작하게 된다.

ASP.NET 또한 ASP.NET 서버 컨트롤과 유사하지만 ASP.NET AJAX 클라이언트 스크립트를 출력해주는 ASP.NET AJAX 서버 컨트롤을 포함한다. ASP.NET AJAX 서버 컨트롤은 서버 기반에서 이들을 개발하고자 할 때 ASP.NET AJAX 클라이언트 스크립트의 프로세스를 간단하게 해준다. 더불어 ASP.NET AJAX는 버튼, 라벨, 옵션, 텍스트 박스, 체크 박스, 하이퍼링크, 유효성 검사 컨트롤과 같은 이미 존재하는 ASP.NET 서버 컨트롤들에 상응하는 서버 컨트롤들을 포함한다. 이들 컨트롤들은 Visual Studio로 통합될 것이며, 디자이너 모드를 통해 표준 ASP.NET 컨트롤들과 같이 사용할 수 있게 될 것이다.

[출처] ASP.NET AJAX란|작성자 장훈

Posted by skensita
Programming/.Net Framework2008. 12. 3. 15:15
XAML이란?
Extensible Application Markup Language 또는 XAML("자멜","자물"로 읽음)은 Microsoft에서 개발한 XML 기반 태그 언어입니다. HTML이 웹 페이지를 시각적으로 표시하기 위해 내부적으로 사용되는 언어인 것처럼, XAML은 Microsoft® Expression Blend™에서 개발한 응용 프로그램을 시각적으로
표시하기 위해 내부적으로 사용되는 언어입니다.

XAML, Windows Presentation Foundation 및 Microsoft .NET Framework 3.0
XAML은 Microsoft® WPF(Windows Presentation Foundation)의 일부입니다.
WPF는 Windows 기반 응용 프로그램 및 웹 브라우저 기반 클라이언트 응용 프로그램의
비주얼 프레젠테이션을 처리하는 Microsoft® .NET Framework 3.0의 기능 범주입니다.
WPF 기반 응용 프로그램은 Windows Vista™ 또는 Microsoft .NET Framework 3.0 및
Internet Explorer 7.0(웹 브라우저 기반 클라이언트 응용 프로그램의 경우)이 설치된
이전 버전의 Windows 환경에서 실행할 수 있습니다.

WPF는 XAML을 사용하여 C#과 같은 프로그래밍 언어가 아닌 태그 언어를 이용해서
시각적으로 탁월한 UI(사용자 인터페이스)를 구성합니다.
컨트롤, 텍스트, 이미지, 도형, 애니메이션 등의 요소를 정의함으로써 XAML로
정교한 UI 문서를 완전하게 만들 수 있습니다.
XAML은 HTML처럼 선언적이므로 응용 프로그램에 런타임 논리를 추가해야 하는 경우에는
코드를 추가해야 합니다.
예를 들어 응용 프로그램이 XAML만 사용하는 경우, UI 요소를 만들어 애니메이션 효과를
적용하거나 이벤트 트리거를 사용하여 해당 UI 요소가 사용자 입력에 일정한 방식으로
응답하도록 구성할 수 있습니다.
그러나 응용 프로그램이 직접 계산을 수행하고 계산에 응답하거나 새로운 UI 요소를
자동으로 만들 수 있으려면 코드를 추가해야 합니다.
XAML 응용 프로그램의 코드는 XAML 문서가 아닌 별도의 파일에 저장됩니다.
이렇게 UI 디자인과 기본 코드가 분리됨으로써, 개발자와 디자이너는
상대방의 작업에 영향을 미치지 않으면서 한 프로젝트에서
더욱 긴밀하게 공동 작업을 할 수 있습니다.

XAML 및 WPF에 대한 자세한 내용은 MSDN의 "XAML 개요"를 참조하거나
Windows Vista Developer Center를 참조하십시오.
Posted by skensita
Programming/WEB2008. 12. 3. 15:13

XML이란

문헌의 구조를 기술하는 메타언어
W3C standard: eXtensible Markup Language(XML)
 

1. 등장배경

  XML은 구조화된 문헌을 웹 상에서  전송할 수 있도록 설계된 표준화된 텍스트 포맷으로 1996년 W3C (World Wide Web Consortium)가 개발하여 1998년 2월 사실상의 표준으로 제정되었다. W3C는 그 목적을 "일반적인 SGML이 웹 상에서 마치 HTML이 웹에서 처리, 이용되는 것처럼 활동할 수 있게 하며 XML은 SGML과 HTML을 같이 사용하면서도 구현하기 쉽고 상호 운용할 수 있도록 고안되었다" 라고 말하고 있다. 즉 각각의 단점은 피하면서 그 장점만을 최대한 살린 언어라는 의미이다.


  SGML은 기기나 처리 시스템에 독립적이고, 문헌을 구조화시켜 그 내용이  물리적인 형태와는 별도로 유지되어 융통성 있고 확장 가능하며 다양한 응용에 사용할 수 있다는 장점이 있는 반면에 기능의 복잡성으로 인해 SGML을 지원하는 소프트웨어의 개발이 쉽지 않으며 비용도 많이 든다.


HTML은 흔히 웹의 언어라고도 하는데 현재 대부분의 웹 페이지는 HTML을 사용하여 작성되었고 넷스케이프 (Netscape)나 익스플로러 (Internet Explorer)와 같은 웹 브라우저들이 이 언어를 인식하고 있다. HTML은 단순성, 이식성, 사용의 용이성이라는 장점을 가지면서도 제한된 태그 집합을 가짐으로써 확장할 수 없으므로 문헌의 여러 가지 특성을 반영시키는 충분한 태그가 없다. 그러므로 문헌을 충분히 표현할 수 없다는 단점이 있다.


 그러나 XML은 SGML을 복잡하게 하는 요인인 많은 선택 기법들을 채택하지 않았기 때문에 복잡하지 않으며 또한 SGML의 장점인 구조성과 융통성을 유지하고 있다. 그리고 XML은 SGML과 마찬가지로 확장 가능하므로 HTML보다 표현력이 있다.   따라서 XML은 SGML의 간단한 하부집합이며 문헌의 유형을 쉽게 정의할 수 있게 한다. 또한 SGML을 따르는 문헌을 쉽게 작성하고 관리할 수 있게 하며 웹 상에서 그러한 문헌들을 전송하고 공유할 수 있도록 한다. 그러면서도 XML을 기술하고 있는 그 명세서 (Specification)의 분량은 SGML의 그것보다 1/10 정도밖에 되지 않는다. 


2 . 목적 및 장점


  W3C에 의하면 XML은 다음과 같은 목적을 가지고 설계되었다.

  ① 인터넷 상에서 쉽게 사용할 수 있어야 한다.

  ② 다양한 어플리케이션들을 지원해야 한다.

  ③ SGML과 호환 가능해야 한다.

  ④ XML 문헌을 처리하는 프로그램을 쉽게 작성할 수 있어야 한다.

  ⑤ XML이 제공하는 선택 기법의 수는 최소로 유지되어야 한다.

  ⑥ XML 문헌은 인간이 읽을 수 있어야 하며 명확해야 한다.

  ⑦ XML의 설계는 빠르게 이루어져야 한다.

  ⑧ XML의 설계는 공식적이고 간결해야 한다.

  ⑨ XML 문헌은 만들기 쉬워야 한다.

  ⑩ XML 마크업의 간결성은 그다지 중요하지 않다.


  이와 같은 목적을 가지고 개발된 XML의 장점은 다음과 같다.

  - 첫째, 장치와 시스템에 독립적이다. 즉 다양한 소프트웨어와 하드웨어에서 이용할 수 있으며 어떠한 XML 소프트웨어에 의해서도 처리될 수 있도록 설계되었다. 


  - 둘째, XML은 매우 명확하다. 선택 기법의 수가 적고 태그의 생략을 유발하는 태그 최소화가 없기 때문이다. SGML이 개발된 당시에는 입력에 대한 부담, 시간, 비용, 저장용량의 제한 등의 이유로 이러한 기법을 허용했으나 기술에 발전에 따라 처리용량의 증가, 코딩을 도와주는 저작 소프트웨어의 개발 등으로 인해 더 이상 문제되지 않는다.
 

  -셋째, 이용자 고유의 태그를 만들 수 있다. 이는 확장성의 개념을 반영하는 것으로서, 이용자의 편의에 따라 혹은 이용자가 가진 데이터의 특성을 반영하거나 구별하고 위해 새로운 태그를 임의로 만들 수 있다는 의미이다. 또한 문헌이 잘 정의되었다면 DTD는 없어도 된다.


  -넷째, XML은 이용자로 하여금 문헌을 여러 방법으로 디스플레이할 수 있게 한다. XML은 문헌의 물리적 구조와 논리적 구조를 분리시키기 때문에 문헌을 여러 방법으로 표현할 수 있다. 


  -다섯째, 특정 언어에 한정되어 있지 않다. XML은 ISO 10646 (Unicode)을 수용하고 있기 때문에 어떤 언어라도 마크업에 사용할 수 있다. 따라서 이는 XML이 언어나 국가에 대한 제한없이 국제적으로 사용될 수 있게 하는 특징이다.


3. 구성(문법)


  - XML (Extensible Markup Language): 문헌의 구조와 내용을 표현

  1) XML 문헌의 구조

  모든 XML 문헌은 엔티티 (entity)라고 부르는 가상의 저장 단위로 이루어진 물리적 구조와 선언, 주석, 문자참조, 엘리먼트, 처리규칙 등을 포함하는 논리적 구조를 가지고 있다. 이러한 XML 문헌은 다시 XML 선언부 (XML Declaration), 문헌유형정의부 (Document Type Definition), 실제 문헌부 (Document Instance)로 나뉜다. 

  그러나 XML 문헌은 SGML과는 달리 문헌이 well-formed되었다면 DTD를 사용하지 않아도 된다. well-formed 문헌이란 적절하게 선언된 물리구조에 따라 정확한 형식으로 작성된 XML 문헌으로서 DTD없이도 유효하다. XML의 well-formed 문헌이 되기 위해서는 실제 문헌이 XML에서 정한 규칙에 따라야 한다.


그 규칙은:

 - 문헌은 하나 이상의 엘리먼트를 포함해야 하고 이들은 모두 시작 및 종료 태그로 한정되어야 하며 서로 적절히 중첩되어야 하고 모든 엔티티와 어트리뷰트는 선언되어야 한다는 등의 여러 가지 제약 조건을 만족시켜야 한다. 잘 정의된 문헌에 한해서 DTD의 부재를 허용하는 XML은 복잡한 DTD의 작성 및 검증 과정을 피할 수 있게 하여 시간과 비용을 절약할 수 있도록 하였으며 DTD에 관한 깊은 지식이 없는 사람도 XML 문헌을 비교적 쉽게 작성할 수 있도록 한다는 이점이 있다. 그럼에도 불구하고 XML에 유효한 문헌은 DTD를 가지고 작성하는 것이 훨씬 쉽다.


 다음은 XML의 구조이다.

* XML 선언부

XML 선언부는 해당 문헌이 XML 문헌임을 알리고 사용하고 있는 XML의 버전, 인코딩 방식에 관한 정보를 표현한다. 다음은 XML 선언부의 예이다.

<? xml version = "1.0"  encoding = "UTF-8" ?>

이 선언은 현재 사용하는 XML의 버전이 "1.0"이고 인코딩은 "UTF-8 (Unicode Transformation -8bit)" 방식을 사용하고 있음을 기술하고 있다.


* 문헌유형정의부

문헌유형정의부는 XML 문헌이 따르고 있는 규칙을 정의한 것이다. 이러한 DTD는 미리 정의된 외부 파일을 부르는 외부 참조의 형태를 지닐 수도 있고 문헌 내부에 직접 포함될 수도 있다. DTD는 크게 엘리먼트, 어트리뷰트, 엔티티 선언으로 이루어져 있다. 엘리먼트 선언 (Element declaration)은 XML 문헌이 가지는 엘리먼트의 명칭, 내용 등을 기술한다. XML 문헌은 수많은 엘리먼트를 가질 수 있지만 최상위 엘리먼트는 단 하나이어야 한다. 이러한 엘리먼트는 태그에 의해 구분되는데 내용이 있다면 시작태그와 종료태그로 엘리먼트의 경계를 표시해주고, 내용이 없다면 태그의 끝 부분에 "/"을 포함시켜 '이 엘리먼트는 아무런 내용이 없음 (empty element)'이라고 표시한다. 다음은 엘리먼트 선언에 관한 예이다.


<!ELEMENT  paragraph    - -     (#PCDATA, emptyspace)      >

<!ELEMENT  emptyspace    - -      EMPTY  >


<paragraph>모든 언어와 어플리케이션에 적합한 단일한 코딩 스킴을 고안하는 것은 불가능하다.<emptyspace/>대신 서로 다른 환경 내에서도 교환할 수 있도록 하는. . . . . . </paragraph>

어트리뷰트 선언은 엘리먼트와 그것이 가진 성질, 즉 어트리뷰트, 그리고 그 값을 연관시키기 위한 것이다. 그러므로 어트리뷰트 선언은 주어진 엘리먼트 유형과 관계된 어트리뷰트의 집합을 정의하고 이러한 어트리뷰트에 제한을 주는 유형 집합을 설정하고 어트리뷰트를 위한 값을 부여하는데 사용된다.

다음은 어트리뷰트 선언의 예이다.


<!ATTLIST  picture
               type  NOTATION  (format1 | format2)  "format1"
               image  CDATA  #IMPLIED  >


엔티티 선언은 엔티티라는 하나 이상의 가상적인 저장 단위를 정의하기 위한 것이다. 이는 문헌의 어떤 부분일 수도 있고 텍스트나 바이너리 (binary) 데이터를 포함한 외부 파일에 대한 참조일 수도 있다. 선언된 엔티티는 문헌내 또는 DTD내에서 여러 번 참조될 수 있다. 다음은 엔티티 선언의 간단한 예이다.

<!ENTITY  ProductName "RF-2000-QJ-46" >
<p>이 제품의 명칭은 &ProductName; 으로서 다음과 같은 기능을. . . . . </p>

* 실제 문헌부

  이는 XML의 DTD에서 정의한 모든 규칙에 따라 문헌이 구조화된 XML 문헌의 실제 내용이다.


4. XML의 응용


  - XLL (Extensible Linking Language): 웹 상에서 활용할 수 있도록 링크 정보를 표현

  - XSL (Extensible Style Language): 문헌의 외양 (스타일) 혹은 출력 형식을 정의


1) XLL (Extensible Linking Language)

  XLL은 XML을 위한 표준적인 링킹 모델 (linking model)을 제공하는 언어로서 기존의 HyTime과 TEI의 많은 기능을 수용하여 단순화시켰다. 이는 XML을 웹 상에서 활용할 수 있게 하는 원동력으로서 XML 문헌이 참조하는 정보원간의 관계를 링크로서 표현하며, 문헌 내부 또는 외부에 존재할 수 있는 이러한 링크를 표현하기 위한 효과적이고 간단한 구조를 가지고 있다. 또한 XLL은 현재 많이 사용되고 있는 HTML의 링크와의 상호 운용성을 고려하여 설계되었다.


  XLL은 다양한 유형의 위치 식별자 (locator), XML과 SGML 데이터내 정보원의 위치 등에 관해 기술한다. 예를 들어 XML-LINK라는 어트리뷰트를 가진 모든 엘리먼트는 링크를 의미하며 그 엘리먼트의 값은 엘리먼트가 가진 링크를 명세한다.


 이러한 XLL은 둘 이상의 정보원과 연관 있는 확장된 링크, 정보원을 위치시키는 방법, 링크가 가진 의미에 대한 통제방법 등을 제공한다.  XLL이 지원하는 링크 유형은 크게 SIMPLE과 EXTENDED로 나눌 수 있다. 단순 링크 (Simple link)는 HTML의 링크와 유사한 것으로 2개의 정보원간의 링크를 식별하며 항상 단방향이고 URL (Uniform Resource Locator)로 정보원의 위치를 지시한다. 확장 링크 (Extended link)는 둘 이상의 정보원간의 관계를 표현하며 양방향 혹은 다중 링크가 가능하다.


2) XSL (Extensible Style Language)

  마크업을 사용하여 문헌을 구조화시키는 방법의 가장 큰 장점은 문헌의 내용과 외양 (스타일)을 분리시킨다는 것이다. 현재 이러한 목적을 위해 HTML은  CSS (Cascading Style Sheets)를 사용하며, SGML은 DSSSL (Document Style Semantics and Specification Language)을 사용하고 있다. 그러나 기능 면에서 CSS는 강력하지 않고 DSSSL은 사용하기 어렵고 복잡하다. 따라서 XML 문헌의 외양을 처리해주기 위한 방법으로서 간단하면서도 강력한 기능을 가진 XSL이 개발되었다.

  XSL은 DSSSL에 기반하여 단순화시켰으며 CSS를 지원한다. 또한 확장 가능하므로 stylesheet 설계자가 다양한 새로운 태그를 만들 수 있고, 출력 (printing)과 온라인 디스플레이 (online display)를 지원한다. XSL은 현재 표준화 작업 중이다.


출처 sookmyung.ac.kr/~ksh/xml.htm

Posted by skensita
Programming/Kernel / Driver2008. 12. 3. 12:03

1. 드라이버의 작동 방식.

 운영체제는 하드웨어와 관련된 많은 동작을 수행하기 위해서 관련 서브 루틴 집합을 구현해 놓고있는데.
쉽게 말하면 드라이버는 이 서브루틴 집합을 담아두는 컨테이너라고 생각하면 된다.
이 컨테이너의 내용물은  DriverEntry, AddDevice, IRP(I/O request packet<- 앞으로 자주 나올놈이니 꼭 기억해두두록하자)처리를 위한 디스 패치 함수 등이 들어있다. 대부분의 드라이버는 몇 가지 종류의 IRP를 처리하는 디스패치 함수를 갖고있따.

WDM 드라이버 개발자는 이렇든 자신의 컨테이너에 포함시킬 기능들을 적절히 선택해서 조합하는 역활을 해야하는것이다.

                                    *컨테이너*

기본드라이버루틴          I/O컨트롤루틴            디스패치루틴

   DriverEntry               AdapterControl            DispatchPnp      
   AddDevice                    StartIO                      DispacthPower  
                                        Onlnterrupt                DispatchWmi
                                         DpcForlsr                  DispatchRead
                                                 ..                          DispatchWrite
                                                                                         ..

2. 어플리케이션의 작동 방식

"서브루틴들의 패키지(pacage of subroutines)" 모델인 드라이버를
"주프로그램과 조력자(main program and helper)" 모델인 일반 어플리케이션과 대비해서 생각해 보자.

ex>

 int main(int argc, char* argv[])
{
    printf("HELLO, WORLD");

    return 0;
}

이 프로그램은 main이라는 이름의 주프로그램과 보조 루틴들의 라이브러리로 구성되어있다.
보조 루틴중 하나인 printf는 표준 출력 파일에 메시지를 프린트한다.
주 프로그램이 들어있는 소스 모듈을 컴파일 하고, 이를 printf와 같은 보조 루틴들이 들어있는 런타임 라이버리와 링킹하고 나면, HELLO.EXE라는 실행 파일이 완성 될것이다.


* 다음은 어플리케이션에 대한 몇 가지 공통사항!

어플리케이션이 사용하는 특정 보조 루틴들은 정적 라이브러리에 포함되어 있고 linkage 에디터는 빌드 과정에서 이것들을 추출하게 된다. 일반적으로 printf같은것들이지. 일부 보조 루틴들은 시스템 DLL로부터 동적으로 링크되기도 한다. 이런 루틴들에 대해 linkage에디터는 실행 파일에 특별한 improt 레퍼런스를 삽입하여, 나중에 런타임 로더에서 이 레퍼런스가 실제 시스템 코드를 가리키도록 한다.
사실, 어플리케이션 프로그램에서 사용되는 모든 Win32 API는 동적으로 링크되어 잇기 때문에, Windows 프로그래밍에서 동적링크는 매우 중요한 개념임!!!


3. 디바이스 드라이버

Hello.EXE와 같이 드라이버도 역시 일종의 실행파일이란것을 알아두자!
파일 확장자는 ****.SYS이지만, 이 파일 구조는 다른 32비트 Windows나 콘솔 모드 어플리케이션과 동일함!!!!!<-
또한 HELLO.EXE와 마찬가지로 드라이버도 많은 보조 루틴을 사용하는데, 운영체제 커널이나 class driver나 다른 지원 라이브러리 에서 동적으로 링크된다. [ 또, 드라이버 파일도 심볼릭 디버깅 정보와 리소스데이터를 가지고있다. ]<- 심볼릭 디버깅등검색해보자!

  *드라이버에 대한 시스템의 역활

HELLO.EXE와는 달리, 드라이버는 main 프로그램을 포함하고 있지 않으며 대신!! 시스템의 판단에 따라 호출할 수 있는 서브 루틴들의 집합을 가지고있다.
서브루틴들은 드라이버나 정적 라이브러리나 운영체제 내에있는 여러 보조 루틴들을 사용할수 있지만. 드라이버는 자신의 하드웨어 외 다른것에는 관여하지 않는다.  그외 다른 부분은 모두 시스템이 담당하고있다.(예를들어 드라이버의 실행 시점 판단이라던가...)


 * 운영체제가 드라이버 내의 서브루틴을 호출하는 과정을 간단히 예를 들어보자!!

1) 사용자가 디바이스를 꽂으면, 시스템은 드라이버의 실행 파일을 가상 메모리에 올리고, DriverEntry 루틴을 호출!!  DriverEntry는 몇가지 작업을 하고 리턴~

2) PNP(Plug and Play) Manger는 드라이버의 AddDevice 루틴을 호출!! 역시 작업후 리턴~

3) PNP Manger가 드라이버에 IRP를 전송하면 디스패치 함수가 이를 처리하고 리턴!

4) 어플리케이션이 디바이스의 핸들을 열면 시스템이 또 다른 IRP를 전송하고, 디스패치 함수가 처리후 리턴!

5) 어플리케이션이 데이터를 읽으려고 시도하면, 시스템이 해당 IRP를 전송! 이에 대해 디스패치 루틴은 IRP를 큐에 저장하고 리턴!!!

6) 드라이버에 연결되어 있는 하드웨어 인터럽트에 신호를 보내서 이전의 I/O 오퍼레이션을 완료시킴.
   인터럽트 루틴에서는 DPC 스케줄링 등의 작업을 한후에 리턴!!!

7) DPC 루틴이 실행되어 5번작업에서 큐에 넣었던 IRP를 삭제하고 , 데이터를 읽도록 하드웨어를 작동시킨후 시스템으로 리턴~~~~~~~~~~

8) 시스템이 드라이버의 서브루틴들을 사용중. -ㅈ- 시간이 흐름.

9) 마침내, 유저가 디바이스를 제거. PNP Manger는 IRP를 드라이버로 전달하고 , 드라이버는 이를 처리한다음 리턴.
 운영체제는 드라이버의 Driver UNload 루틴을 호출해서 몇가지 일을 처리하고 리턴.
 최종적으로시스템은 가상메모리에서 드라이버 코드를 제거~~~~~~~~~~~~~~~~

 

4. 쓰레드와 드라이버 코드.

 드라이버가 어플리케이션과 다른점!
드라이버는 코드를 실행시키기 위해 시스템이 특별히 쓰레드를 생성시키지는 않는다는것!
대신 시스템이 드라이버의 서브루틴을 호출하기로 결정하면 그 순간 실행되고 있던 쓰레드 컨텍스트에서 드라이버 코드를 실행시킴!!!!

하드웨어 인터럽트가 발생하는 순간 모든 쓰레드들 중에서 어떤 것이 우연히 실행되고 있을지 알순 없지.
이것을 임의의(arbitrary) 쓰레드라고 부르며 "임의의 쓰레드 컨텍스트에서 실행된다" 라고 말함!

즉, 드라이버의 서브루틴을 호출하려 할 때, 대부분 임의의 쓰레드 컨텍스트에서 돌아가고 있을것이다.

예를들어, 자신의 드라이버의 ISR(Interrupt Service Routine)이 통제권을 가지는 순간 어떤 컨텍스트가 올지 모른다는거~

흔히 storage 드라이버의 경우에서 볼수있는데, 파일시스템 드라이버가 읽기/쓰기에 최종적인 책임을 지고 연관된 드라이버를 컨트롤 하는 형태로 되어있음!

하지만 항상 임의의 쓰레드 컨텍스트에서 드라이버 코드를 실행시키는것은 아님!

PsCreateSystemThread를 사용해서 자신의 시스템 쓰레드를 생성하거나 work item을 스케줄링해서 특정쓰레드를 요청할수도있음.

쓰레드가 임의적인지 아닌지가 왜중요하냐!


첫번째로, 드라이버는 임의의 쓰레드를 "블록킹" 해서는 안된다는거.

다른 쓰레드에 도움이 되는 작업을 수행한다고 해서 또다른 쓰레드를 중지시키는건 공평치 못하겠지?


두번째로, 드라이버가 IRP를 생성해서 다른 드라이버에게 이를 전달하는 경우인데
...

임의의 쓰레드에서는 비동기적 IRP만생성가능. 그러나 비임의 쓰레드에서는 동기적IRP도 생성가능하기때문이지.

동기적 방식에서는 I/O Manager는  IRP를 생성한 그 쓰레드의 컨텍스트에 IRP를 속하게 하고, 쓰레드가 종료되면 IRP를 자동으로 취소함.

 그러나 비동기적 IRP인경우,  I/O Manager는 이를 특정한 쓰레드에속하게 하지는 않음. 따라서 비동기적 IRP를 생성한 쓰레드는 드라이버에서 수행하는 I/O 오퍼레이션에 대해 직접적인 관계가 없으며, 이쓰레드가 종료됬다고 IRP를 취소시키지도 않는다는거지.



5. 시스템의 드라이버 로딩 방식

하드웨어가 플러그 앤 플레이(PNP) 를 지원하는지 여부에 따라 두 가지 조금 다른 방법을 사용한다.

1) 플러그 앤 플레이 디바이스는 시스템이 감지할 수 있는 전자 서명을 가지고 있음.
시스템 bus driver는 하드웨어의 존재 유무를 파악한 후, 어떤 종류의 하드웨어 인지 판단하기 위해 서명을 읽어옴
그 후 시스템은 레지스트리와 INF 파일을 이용해 자동으로 가장 적당한 드라이버를 로드하게 됨!!

2) Legacy 디바이스는 전자서명이 없다!!!  따라서 시스템이 자동으로 디바이스를 감지할수 없뜸.

그래서 사용자가 새 하드웨어 추가 마법사를 사용해서 검색해야함. 그러고나면 시스템은 레지스트리와 INF를 이용해 자동설치를한다!

Posted by skensita
Programming/Kernel / Driver2008. 12. 3. 11:58

WINDOWS XP 운영체제.

--------------------------------------------------------------------

어플리케이션     ->

                              WIN32 API 호출

WIN32서브시스템<-                                                                          유저모드

--------------------------------------------------------------------

                        ->                                                                         커널모드

                              시스템 서비스 인터페이스

                        <-

I/O MANAGE(디바이스 드라이버) -> HAL 호출

                            HAL(하드웨어 추상화 계층)

                                       -하드웨어-

---------------------------------------------------------------------



*WINDOWS 98/ME 하고 WINDOS 2000/XP 는 내부 동작이 전혀다름. 따라서 디바이스 개발도 다름.


*FILE SYSTEM DRIVER(파일시스템드라이버) : 명명된 파일(NAMED FILE)이 포함된 계층적 디렉토리 구조의 개념을 가진

표준 PC파일 시스템 모델을 로컬 하드디스크나 네트워크 연결에 대해 구현한다. 커널 모드 드라이버이다.


*LEGACY DEVICE DRIVER(레거시 디바이스 드라이버)  : 다른 드라이버의 도움 없이 하드웨어 디바이스를 직접적으로 컨트롤 하는 드라이버이다. 이 븐류에는 XP와 호환되는 NT 드라이버가 포함된다.


*WDM 드라이버 (윈도우즈 드라이버 모델)의 하부 드라이버 .


CLASS DRIVER - MICROSOFT에서 작성. 건드릴 필요없음.


MINI DRIVER - CLASS DRIVER와 함께 동작. 디바이스를 책임지고 있지만 클래스 드라이버의 서브루틴을 이용하며

클래스 드라이버는 하드웨어 관리를 맡고 있지만 많은 종속적 디바이스를 처리하기위해 MINIDRIVER를 역호출하게된다.

사용예-

(USB가 아닌 휴먼입력장치(HUMAN INPUT DEVICE:HID). 마으스, 키보드, 조이스틱, 게임 휠.

 스캐너와 카메라 같은 WINDOWS 이미지 수집 (WINDOWS IMAGE QCQUISITION:WIA) 디바이스.

 오디오,DVD,비디오 디바이스와 같은 스트리밍 디바이스와 멀티미디어 데이터 스트림

 비디오카드. 프린터. 배터리

 USB와 1394등 전통적이지 않은 버스를 사용하는 네트워크 인터페이스 디바이스. 이러한 디바이스에 대해서는 NDIS(NETWORK DRIVER INTERFACE SPECIFICATION)미니포트 드라이버를 만들어야한다. DDK 문서에서는 이를 "WDM LOWER EDGE"로 작성하라 권하고 있다. 이런 드라이버는 운영체제간에 호환성을 가지기가 어려우므로, 플랫폼 의존성을 해결하기 위해서는 작은 차이점을 가진 몇 가지 버전으로 만들도록 처음부터 계획해야한다. )



FILTER DRIVER - 경우에따라 마이크로 소프트가 제공하는 범용 드라이버가 완전한 요구사항과 맞아떨어지지 않을경우 필터드라이버를 작성해서 범용 드라이버의 작업을 수정하는것.



단일 WDM FUNCTION DRIVER - 이 드라이버는 기본적으로 독립적인 개체이고, 하드웨어를 제어하는 모든 세세한 부분을 처리.

사용예-

(스마트카드 리더, 디지털-아날로그 컨버터, 소유권확인태그 등등)


*SCSI(SMALL COMPUTER SYSTEM INTERFACE) 어댑터 : "SCSI MINIPORT" 드라이버를 사용하며, 다른 표준 커널 지원 함수를 전혀 사용하지 않는다. 이드라이버는 대신 SCSI-PORT.SYS 나 SCSIPORT.VXD에 의해 EXPORT된 특별한 API를 사용.


*네트워크 인터페이스 카드는 "NDIS MINIPORT 드라이버"를 사용. NDIS.SYS나 NDIS.VXD에의해 EXPORT된 특별한 API를 사용

Posted by skensita
Programming/Kernel / Driver2008. 12. 3. 11:57

WDM방식이란, 윈도우환경에서 디바이스드라이버를 작성하는 방법을 획일화 한 것이다. 이 방법으로 디바이스드라이버를 작성하면, 윈도우의 확장 버젼이 나오더라도, 쉽게 이 디바이스드라이버코드를 그대로 사용할 수 있는 장점을 가지고 있다.
그렇다고 모든 디바이스드라이버를 WDM방식으로 작성할 수 있는 것은 아니라는 것을 명심해야 한다. WDM방식의 디바이스드라이버를 작성하기 위해서는 윈도우가 어느 정도만큼 이런 모델을 지원하고 있는가를 알아야 한다
.

예를 들어, 윈도우 9x에서 사용하는 USB이동식디스크를 생각해보자. USB이동식디스크를 윈도우 9x에서 사용하려면 디바이스드라이버가 필요한데, 이때 WDM디바이스드라이버가 사용될 수 있을까? 정답은 그렇다 이다.

USB버스를 사용하는 디바이스를 구동하는 드라이버이기 때문에 WDM디바이스드라이버를 작성해야 한다. 결국, 윈도우에서는 USB버스를 사용하려면 WDM디바이스드라이버모델을 사용해야 한다는 것이 된다. 그런데, 윈도우 9x에서는 디스크드라이버로서는 WDM방식을 사용할 수 없다는 것도 알아야 한다. 이상하다. USB디스크드라이버는 그렇다면 어떤 드라이버모델을 사용해야 한다는 것 일까요?


결국 2가지를 사용해야 한다는 것이다. 하나는 USB버스를 사용하기 위한 WDM디바이스드라이버이고, 또 다른 하나는 윈도우9x에서 디스크드라이버로 사용되기 위해서 VxD라는 모델을 사용하는 디바이스드라이버가 된다.
만일, 윈도우9x가 디스크드라이버로서 WDM을 지원하고 있었다면, USB이동식디스크를 위한 디바이스드라이버는 달랑 WDM드라이버 하나만 잘 만들면 된다.
윈도우2000은 하나의 WDM드라이버만으로 이것들이 해결된다. 윈도우2000에서는 디스크드라이버의 역할을 WDM디바이스드라이버가 수행할 수 있거든. 윈도우가 지원하는 것이다.
그러니까, 윈도우2000에서는 USB버스를 사용하는 WDM디바이스드라이버의 코드 안에다 디스크역할을 수행하는 코드를 포함하면 간단히 USB이동식디스크드라이버가 만들어지는 거가 되다.

이렇게 WDM방식으로 디바이스드라이버를 만들게 되면, 이 드라이버가 어디까지 현재 사용되는 윈도우에서 지원되고 있는가를 분명히 알아야 한다.

만일, USB이동식디스크드라이버를 윈도우9x에서 만들려고 할 때, 실컷 WDM방식만을 생각하고 만들었다면, 나중에 땅을 치고 후회하게 된다. VxD를 생각해야 하니까..

WDM
방식을 조금 더 구체적인 부분까지 설명해 보도록 하자.

 

 

1. WDM디바이스드라이버의 의미


WDM
디바이스드라이버에서 사용되는 WDM이란 용어를 풀어서 보면, Win32 Driver Model이 된다. 물론, 어떤 책에서는 Windows Driver Model이라고도 설명하지만, 보통은 이보다 Win32 Driver Model이란 표현이 더 정확할 것이다.

Win32 Driver Model
이란 표현이 암시하는 것이 무엇일까? 그것은 Win32 Subset을 통해서만 디바이스드라이버에 접근한다는 것을 말한다. 이 의미는 응용프로그램에서 사용하는 SDK(API)중에서 Win32 API를 사용하여 디바이스드라이버에 접근할 수 있다는 것이다. 그것들이 어떤 함수이냐 하면, CreateFile, ReadFile, WriteFile, DeviceIoControl, CloseHandle 이다.

이런 함수의 용도를 보면, 원래는 실제 파일을 읽고 쓸 때 사용하는 거지만, 윈도우에서는 디바이스드라이버와 통신하는 모양을 마치 파일을 다루는 것과 동일하게 간주하려 한다는 것을 암시하고 있다.


파일을 여는 간단한 함수를 예를 들면,

  Handle = CreateFile( “C:\\TEST.DAT”, FILE_READ_DATA|FILE_WRITE_DATA…)

이렇게 함수를 사용하면 무엇을 기대하지? 그것은 아마도 C:\TEST.DAT라는 파일이 열릴 것으로 생각이 든다. 그런데, 이 모양을 조금 더 자세히 살펴보자.


C:\TEST.DAT
라는 문장은 크게 3가지로 구분 되어질 수 있다.
C:
이것은 볼륨을 나타내는 심볼 이름이고

\
이것은 볼륨과 그 다음을 구분하는 구분자 이고
..
TEST.DAT
는 볼륨아래에서 찾게 되는 파일이름이 된다
.

이렇게 3가지로 구분되어서 사용되는 이런 파일열기에서는 다음과 같은 일이 예상된다
.
응용프로그램 -> 파일열기(C:\TEST.DAT) -> 운영체제 -> C: 볼륨을 처리하는 디바이스드라이버(볼륨파일시스템) -> \ 단어를 구분하여, 그 아래에 존재하는 TEST.DAT라는 문장을 찾는다. -> 결국 TEST.DAT라는 파일을 찾기 위해 실제 디스크드라이버를 호출한다
.

이렇게 파일을 여는 단순한 명령을 보아도, 우리는 이곳에서 C:라는 볼륨을 처리하는 디바이스드라이버가 사용된다는 것을 알 수 있다. 이처럼 파일열기명령으로만 알았던 CreateFile이 실제로는 디바이스드라이버를 여는 명령이란 것을 알 수 있다
.
이렇게 CreateFile함수를 통해서 디바이스드라이버를 열게 되면, C:볼륨을 처리하는 디바이스드라이버는 적절한 핸들 값을 리턴 하여, 응용프로그램이 차후에 이 핸들을 사용하여 ReadFile, WriteFile등의 함수를 호출하게 되며, 이런 함수를 통해서 호출하는 Read, Write의 요청을 윈도우운영체제는 핸들 값을 통해서 적절한 디바이스드라이버를 찾게 된다
.

파일을 읽는 명령을 예를 들면

응용프로그램 -> 파일읽기(ReadFile) -> 운영체제, 사용된 파일핸들을 분석하여 이것이 C:볼륨파일시스템이라는 것을 찾아낸다. 그런 다음, C:볼륨을 처리하는 디바이스드라이버(파일시스템)를 호출한다 -> C: 볼륨을 처리하는 디바이스드라이버 ..
이렇게 호출관계가 되어진다는 것을 명심하면, WDM디바이스드라이버가 어떤 방법으로 응용프로그램과 통신하게 되는지를 추측할 수 있게 된다

.
결국, WDM디바이스드라이버는 다음과 같은 호출관계에 놓이게 된다.
응용프로그램 -> API(File을 다루는 함수들) -> 운영체제 -> WDM디바이스드라이버
이럴 때 사용되던 API함수들이 Win32 API함수이기 때문에 우리는 Win32 Driver Model이란 표현을 사용하게 되다. 그 말은 이런 함수를 통하지 않고는 응용프로그램이 WDM디바이스드라이버와 통신할 수 없다는 것이 된다.
윈도우9x에서 사용되는 VxD는 상대적인 의미를 가지게 되다.
윈도우9x에서 단순히, 메모리를 읽거나, 쓴다든지, 아니면, 입출력포트를 접근해서 키보드 데이터를 읽어 오려 한다든지 하는 동작을 응용프로그램이 하려고 하면, 곧바로 응용프로그램 모르게 윈도우는 현재 제어를 VxD로 뺏어가 버린다. 이런 것과는 차원이 다르다.

 

 

2. WDM디바이스드라이버와 윈도우


윈도우 2000에서는 대부분의 디바이스드라이버를 WDM방식으로 작성할 수 있거든. 그러나, 윈도우9x에서는 그것이 불가능하다. 윈도우9x에서는 WDM보다는 VxD방식으로 작성된 디바이스드라이버를 대부분에 디바이스드라이버에 적용할 수 있도록 윈도우가 지원하고 있다.

윈도우2000이 되어야, VxD는 사라져버리고, WDM방식이 대부분의 디바이스드라이버를 지원할 수 있게 된다. 물론, 모든 디바이스드라이버를 다 WDM방식으로 사용할 수 있다는 것은 절대로 아니다. 예를 들어, 프린터드라이버, 디스플레이드라이버, 네트워크 드라이버 등은 WDM방식으로 만들 수 없다

 

 

3. WDM디바이스드라이버의 내부함수들


아까 1)에서 살펴보았던 내용 중에 응용프로그램 -> API(File을 다루는 함수들) -> 운영체제 -> WDM디바이스드라이버 라는 부분을 다시 한번 생각해보자.

이 내용대로라면, 운영체제 -> WDM디바이스드라이버가 된다는 것이다
.
이렇게 된다는 의미라면, 결국 운영체제가 직접 WDM디바이스드라이버를 호출하는 것이 된다. 이렇게 운영체제가 우리가 만든 WDM디바이스드라이버를 호출하려면 어떻게 WDM디바이스드라이버를 만들어야 할까? 운영체제가 알아서 여러분들을 호출할까? 그냥 호출하는 것이 아니라 어느 정도의 약속이 되어지는 부분이 필요하다.


그것이 호출약속이 된다. WDM디바이스드라이버는 최소한 하나의 함수를 외부에 Export해야 할 의무가 있다. 그래야, 운영체제는 이 함수를 통해서 WDM디바이스드라이버와 통신할 수 있다. 그 함수가 바로, DriverEntry()함수가 된다.


이 함수는 유일하게 Export되어지는 함수이기에, 반드시 C로 컴파일하는 것이 좋다. 만일, C++로 컴파일하게 되면 다 아는데로, 언어의 특징상 다형성이 가미되어 맹글링문제가 생겨서 실제로 DriverEntry()란 함수는 없어지고, 그 자리에 DriverEntry@Ad23dsd42ZSER 이런 이상한 이름의 함수가 만들어진다. 이런 함수가 만들어지면, 당연히 운영체제는 이 함수를 호출할 수 없다. 이름이 어려워진다.

이렇게 WDM 디바이스드라이버가 가진 DriverEntry()함수를 운영체제가 호출하면, 드라이버는 무엇을 하느냐? 그것은 바로, WDM디바이스드라이버가 가진 호출을 원하는 자신의 함수들을 등록하는 것이다. 결국, WDM디바이스드라이버는 10개정도의 함수를 가지고 있는 상태에서, 이 함수를 운영체제가 호출하지 못하니까 일단, DriverEntry()함수를 먼저 공개하고, 이 함수가 호출되었을 때, 나머지 자신의 함수들을 정해지 방법을 사용해서 운영체제에게 공개하는 것이다.

 

 

여기서는 함수들을 모두 이해하는 것은 어려울 것 같고.. 어떤 함수들이 존재하는 대강 알아두자..

 

. DriverEntry() : 함수이름이 반드시 유지되어져야 한다.
. SAMPLEAddDevice() :
함수이름자체는 무의미하다. 역할만 중요하다
.
. SAMPLEIRPDispatch() :
함수이름자체는 무의미하다. 역할만 중요하다
.
. SAMPLEDriverUnload() :
함수이름자체는 무의미하다. 역할만 중요하다
.
. SAMPLEIRPStartIo() :
함수이름자체는 무의미하다. 역할만 중요하다.

                                              

 

특별한 일을 수행하지 않는 간단한 WDM디바이스드라이버의 골격은 다음 4가지 엔트리로 구성된다.


. DriverEntry Routine
. AddDevice Routine
. IRP Dispatch Routine
. DriverUnload Routine


이 중에서도 DriverEntry Routine은 디바이스드라이버코드의 시작위치가 된다. 그리고, 이곳은 코딩상에서 함수명을 반드시 "DriverEntry"라고 가져야 하는 특징을 가진다. 그리고 다른 함수들은 실제 함수의 시작주소를 디바이스드라이버코드가 수행될 때 드라이버코드내에서 직접 구해서 IO MANAGER에게 알려주는 반면에 "DriverEntry"함수는 외부에 Export되는 유일한 이름이다. 따라서, "C++"언어를 사용하는 경우에는 특히, extern "C"명령을 사용해서 “DriverEntry"함수를 정의해야만 "C++"언어가 가지는 다형성을 위한 Mangling문제에서 벗어날 수 있다.


) extern  "C"  NTSTATUS  DriverEntry(..)

그리고, DriverEntry Routine AddDevice Routine은 윈도우즈가 제공하는 “SYSTEM" Process의 쓰래드아래서 호출된다. 쉽게 이해하자면, ”SYSTEM.EXE"라는 응용프로그램을 하나 만들어서, 이 프로그램이 DriverEntry, AddDevice Routine을 호출하는것이라고 생각해도 좋다. 윈도우에서는 특정 Process 아래에서 수행되는 Thread Task Switching을 허용한다. 그렇기 때문에 디바이스드라이버개발자들은 이곳에서 Event(이벤트)를 기다리는 행동을 한다든지, 아니면 이런 행동을 할것으로 기대되는 운영체제의 함수들을 호출하는 행동을 해도 좋다. 이렇게 Event를 두고 기다리는 행동은 자연히 태스크 스위칭을 일으키기 때문이다.

 

 

WDM디바이스드라이버가 가지는 함수 엔트리들은 이 밖에도 많이 있지만, 꼭 있어야 하는 중요한 엔트리 3가지만 살펴보도록 하자.

(1) DriverEntry Routine


WDM
디바이스드라이버코드에서는 다음과 같이 정의하여 사용한다.

 
extern  "C"
 NTSTATUS
 DriverEntry( PDRIVER_OBJECT  pDriverObject, PUNICODE_STRING  pRegistryPath )
 {
 ................
 }

이곳은 WDM디바이스드라이버가 메모리에 적재되어 운영체제로부터 호출되는 가장 처음의 함수 엔트리가 된다. 디바이스드라이버가 메모리에 적재되는 경우에 가장 먼저 호출된다는 특징을 가지기에, 디바이스드라이버개발자들은 이곳에서 몇 가지 코드를 구현하려 한다. 이때, 주의할 점은 “DriverEntry"가 호출되는 것은 단지, 디바이스드라이버가 메모리에 적재되어서 처음 실행된다는 점을 생각 해야 한다. 그 외에 이 시기가 디바이스드라이버에 입장에서 현재 자신의 하드웨어장치를 마음대로 초기화하는 등의 작업을 하도록 허용된 시기는 아니라는 것이다. 운영체제는 이처럼 하드웨어장치를 사용하라는 의미로 ”DriverEntry"를 호출하는 것이 아니라, 드라이버가 메모리에 처음 적재되는 경우에 필요로 하는 내부 변수 등을 초기화하는 작업을 디바이스 드라이버 측에서 먼저 수행하라는 의미에서 호출하는 것을 명심해야 한다.

WDM
디바이스드라이버에서는 똑같은 하드웨어장치를 같은 PC에 여러 대 설치한다 하더라도, 똑같은 디바이스드라이버를 여러 번 메모리에 적재하지 않는다. 예를 들어, 같은 회사에서 만든 USB이동식 디스크를 하나의 PC 2대를 연결 한다 하더라도, 디바이스드라이버는 단 한번 메모리에 로딩된다는 것을 의미한다. 결국, “DriverEntry"는 디바이스드라이버입장에서 DriverEntry, 자신이 사용할 하드웨어장치가 똑같은 종류의 것이 2개건, 3개건간에 단 한번만 호출된다.

 

 

WDM디바이스드라이버는 사실 IO MANAGER의 내부 루틴 혹은 내부모듈에 불가하다. 따라서, IO MANAGER가 원하는 방법대로 함수 엔트리를 준비하지 않으면 WDM디바이스드라이버로서 역할을 수행할 수 없다. IO MANAGER “DriverEntry" 함수를 호출하는 목적을 단지, WDM디바이스드라이버 자체가 사용할 내부변수를 초기화하는 목적에만 두지 않는다. DriverEntry함수를 호출함으로써, WDM디바이스드라이버가 가지고 있는 다양한 함수 엔트리들, 결국 IO MANAGER가 필요로 하는 형식을 가지는 함수 엔트리들에 대한 주소를 IO MANAGER에게 알려주는 목적을 달성하게 된다. WDM디바이스드라이버의 함수 엔트리를 얻기 원하는 IO MANAGER의 목적은 “DriverEntry"함수의 파라미터로 전달되는 ”pDriverObject“를 통해서 완성되게 된다. IO MANAGER는 각각의 WDM디바이스드라이버들에게 하나씩의 ”pDriverObject"를 공급하게 되며, 이렇게 공급된 “pDriverObject"의 내용에는 WDM디바이스드라이버가 가진 자신의 함수 엔트리를 등록하도록 되어 있어서, 이를 통해서 IO MANAGER WDM디바이스드라이버가 가지는 함수 엔트리를 원하는시기에 언제든지 호출할 수 있는 정보를 가지게 된다. 따라서, ”DriverEntry"함수가 호출되면, WDM디바이스드라이버가 수행하는 일은 무엇보다도 “pDriverObject"의 내용 중에서 함수 엔트리를 등록하는 부분으로 자신의 함수 엔트리를 등록하는 일이 된다. 이제 “DriverEntry"를 무사히 수행한 WDM디바이스드라이버는 IO MANAGER로부터 언제든지 호출될 수 있는 준비가 되었다. WDM디바이스드라이버에서 이 구조체에 기록하는 자신의 함수포인터들은 2가지 그룹으로 나뉠 수 있다.

- IRP
명령어 처리그룹
  IRP
명령어를 받아들이는 함수들
  : Create, Close, Pnp, Read, Write, IoControl, ..
명령처리함수들

- IRP
명령어 비처리그룹
  IRP
명령어를 받아들이지 않는 함수들
  : AddDevice, Unload, ..
함수들

 

 

다음은 대게의 WDM 디바이스드라이버에서 작성되는 “DriverEntry"함수에서 이 ”pDriverObject"구조체를 다루는 예이다.


 pDriverObject->MajorFunction[IRP_MJ_CREATE] = SAMPLECreateDispatch;
 pDriverObject->MajorFunction[IRP_MJ_CLOSE] = SAMPLECloseDispatch;
 pDriverObject->MajorFunction[IRP_MJ_READ] = SAMPLEReadDispatch;
 pDriverObject->DriverExtension->AddDevice = SAMPLEAddDevice;

예를 보면, SAMPLECreateDispatch, SAMPLECloseDispatch, SAMPLEReadDispatch 함수들은 모두 IRP명령어를 받아들이는 함수들이며, SAMPLEAddDevice 함수는 IRP명령을 받아들이지 않는 함수이다.

함수이름을 보면, "SAMPLECreateDispatch"라고 하는데, 짐작으로는 무엇인가 “Create-열기"작업과 관련이 있어 보인다는 것은 추측이 가능하나, 이 함수 엔트리가 실제로 어떤 역할을 수행하는가는 왼쪽 편에 등록되는 맴버 변수를 통해서 정해져 있게 된다
.
결국, pDriverObject->MajorFunction[] 배열에 등록되는 함수엔트리들의 역할이 이미 등록되는 시기부터 정해져 버린다는것이다.

 

역시 pDriverObject -> DriverExtension -> AddDevice 변수도 역시 마찬가지이다. 이곳에 등록되는 것만으로도 그 역할이 정해져 버린다. pDriverObject->MajorFunction[]배열에 등록되는 함수엔트리들을 “IRP Dispatch Routine"이라고 부른다. 이곳은 명령어(IRP)를 직접 받아들이는 곳이기도 하다. 그리고 pDriverObject->DriverExtension->AddDevice배열에 등록되는 함수엔트리를 ”AddDevice Routine"이라고 부른다.

pDriverObject->MajorFunction[]
변수가 배열구조를 가지고 있으므로, 결국 이 배열에는 첨자가 사용된다. 이 첨자는 다음과 같이 사용되고 있다.

 

 

첨자의 의미를 통해서, 해당하는 첨자를 사용한 pDriverObject->MajorFunction[]배열의 내용이 되는 함수포인터의 역할을 짐작할 수 있게 된다.


"DriverEntry"
가 호출될 당시에 “pDriverObject"내의 함수포인터를 유지하는 대부분의 변수들은 0으로 초기화되어있는 반면, pDriverObject->MajorFunction[]배열의 내용은 “0”으로 초기화되어있는 것이 아니라, 특정 주소 값이 이미 기록된 상태이다. 이는 WDM디바이스드라이버에서 pDriverObject->MajorFunction[]배열의 값들을 변경하지 않더라도, 그 변수의 값은 이미 IO MANAGER가 유지하는디폴트 핸들러의 주소를 가지기 위해서이다
.
디폴트 핸들러는 다음과 같은 형태로 메모리 내에 이미 정의되어 있다
.

또 하나의 “DriverEntry"함수의 파라미터는 ”pRegistryPath"이다. 이곳은 디바이스드라이버를 설치하는 당시에 운영체제에 의해서 지정된 디바이스드라이버를 위한 소프트웨어 서비스키를 가리키는 위치정보를 담고 있다. “DriverEntry"시기에는 다른 레지스트리는 사용이 불가능할수도 있지만, 유독 이곳 ”pRegistryPath"가 가리키는 레지스트리키 만큼은 디바이스드라이버에서 항상 사용이 가능하다는 특징을 가진다. 윈도우즈시스템이 부팅되는 초반시기에 메모리에 적재되는 WDM디바이스드라이버들은 시스템레지스트리를 접근하는데에 있어서 제한을 받게 된다. 이때 “pRegistryPath"에서 가리키는 레지스트리키는 언제든지 접근이 가능하다는점에서 WDM디바이스드라이버들은 이곳을 정보보관장소로 사용하게 된다. 다음은 ”pRegistryPath"가 가리키는 값들의 예이다
.
 


   . “HKLM\System\CurrentControlSet001\Service\SAMPLE"
  . “HKLM\System\CurrentControlSet001\Service\USBSTOR"
  . “HKLM\System\CurrentControlSet001\Service\DISK"

 

[정리]


“DriverEntry Routine"
WDM 디바이스드라이버가 메모리에 적재되는 시기를 알려주는 곳이다. 이곳은 IO MANAGER가 현 WDM 디바이스드라이버가 메모리에 적재되는 것을 알리는 목적과 디바이스드라이버가 가지는 다양한 함수 엔트리들의 주소를 등록 받기 위한 목적을 가진다. 특히, WDM 디바이스드라이버에서는 이 시기에 자신이 사용하려는 하드웨어장치를 적절한 방법으로 초기화하는 것은 권장 하는 일이 못 된다. 하드웨어장치와는 전혀 관련이 없는 루틴이라는 사실을 명심해야 한다.

 

 

(2) AddDevice Routine


USB이동식디스크를 지원하는 디바이스드라이버가 하나 있다고 가정하자. 똑같은 장치 2개를 PC에 연결했을 때, 디바이스드라이버가 2번 메모리에 적재되는 것은 메모리낭비를 초래하는 비 능률적인 운용이 될 수 있다. 결국, 윈도우즈는 이렇게 같은 종류의 여려 개의 장치가 한대의 PC에 연결 되는 경우에 하나의 디바이스드라이버만으로도 이 장치들을 지원할 수 있도록 한다. 이렇게 하나의 디바이스드라이버에서 여러 대의 같은 하드웨어장치를 지원하기 위해서는 디바이스 문맥(Device Context) - “DeviceObject라는 용어를 사용해야 옳은 표현이지만, 지금 시기에는 이해하는 목적을 위해서 디바이스문맥이라는 용어를 임시로 사용한다유지라는 중요한 구현상 특징을 외면할 수 없다. 결국, 디바이스드라이버는 하나의 장치마다 하나의 문맥을 유지할 수만 있다면, 2대 이상의 장치가 연결되더라도 문맥을 통해서 이 장치를 관리할 수 있다. 디바이스문맥이란 용어는 디바이스근거라는 용어와 비슷한 의미로 이곳에서는 보여 질 수 있다. 예를 들어, 하나의 드라이버가 2가지 이상의 자신의 하드웨어장치를 지원하는 모습을 위해서 각각의 하드웨어장치에 대한 자신의 관리를 운영체제에게 알려주는 근거이기도 하기 때문이다.


여기서 디바이스 문맥이라는 것은 구체적으로 “DEVICE_OBJECT"라는 구조체로 표현되어 사용된다. 이 구조체는 뒤에서 자세히 배우지만, 이 곳에서는 ”AddDevice Routine"이 하는 역할을 이해하기 위해서 “DEVICE_OBJECT”구조체의 의미중 일부분에 대해서만 잠시 배우도록 하겠다.

똑같은 USB이동식디스크장치2대를 PC에 연결했다고 가정하자. 사용자는 탐색기를 통해서 2개의 드라이브명을 볼 수 있을 것이다. 이 드라이브명을 “G:", "H:"라고 가정한다. 이때, 사용자가 ”G:"를 접근하려 한다면, 사용자의 이런 접근은 USB이동식디스크장치를 지원하는 디바이스드라이버(이하 디스크드라이버)측으로 적절한 명령이 되어서 전달된다. “H:"드라이브를 사용자가 접근하는 경우에도 마찬가지로 해당하는 디스크드라이버로 명령이 전달된다.그렇다면, 디스크드라이버에서는 어떻게 이 2개의 물리적인 드라이브를 구분할 수 있을까? 앞에서 배운 대로 라면, "DriverEntry"에서 등록한 "MajorFunction[]"배열은 여러 개의 장치를 구분하는 방법을 제공하지 않았으며, 단지 외부로부터 디스크드라이버가 받게 되는 명령어(IRP)를 처리하는 함수 엔트리만을 등록하게 되어있다. 이대로라면, 디바이스드라이버는 자신이 등록한 함수 엔트리안에서 사용자가 접근한 ”G:", "H:"드라이브를 구분할 수 있어야 한다. 이럴 때 바로 문맥(Context)이 필요하다. 명령어(IRP)를 받는 “IRP Dispatch Routine"으로 전달되는 파라미터 중 첫 번째 파라미터 즉 "pDeviceObject"가 전달되는 목적이 바로 이것이다.

 

 

윈도우즈의 도움이 없는 황무지 같은 도스(MSDOS)같은 운영체제만 존재하는 컴퓨터에서 USB이동식디스크를 사용하는 것을 가정해보도록 하자. 윈도우즈에서 보는 탐색기와 비슷한 역할을 수행하는 프로그램이 있어야 한다. 이 프로그램 안에서는 USB이동식디스크를 마음대로 주무르는 코드를 가지고 있을 것이다. USB이동식디스크를 사용하는 사용자를 생각해보자. 이 사용자가 이 이동식디스크를 사용하는데 있어서 당신이 제공하는 탐색기와 같은 프로그램만을 사용하게 된다면 모르지만, 그렇지 않으면 당신은 여러 가지 탐색기 아류작을 만들어야 할 것이다. 사용자의 취향은 다양하기 때문이며, 목적도 다양하기 때문이다. 탐색기를 만들어서 사용자에게 제공하는 당신 입장에서는 앞으로 사용자가 원하는 그런 프로그램이 되기 위해서 계속된 업그래이드뿐만 아니라, 새로운 프로그램이 추가 작성될 수도 있다. 이렇게 사용자가 원하는 모양으로 프로그램이 추가되는 것 뿐 만아니라, 또 다른 기능을 가진 USB이동식디스크가 만들어지면, 이렇게 새롭게 만들어진 이동식디스크를 사용하기 위해서 역시 현재의 프로그램은 수정되어져야 한다.
이런식으로 수정 되어지는 부분은 크게 사용자가 보는 관점에서의 수정과 하드웨어(USB이동식디스크)의 변경으로 인한 수정으로 나뉠 수 있는데, 이렇게 수정되어지는 부분을 고려하기 위해서는 순수한 의미에서 응용프로그램과 하드웨어종속적인 코드를 담고 있는 디바이스드라이버라는 개념이 필요할 것이다.

응용프로그램과 디바이스드라이버를 나눈다는 것은 현실적으로는 하나의 프로그램이 아니라, 2개의 프로그램을 만든다는 것이다. 당신은 어느 쪽이 전문가이겠는가? 응용프로그램이겠는가? 아니면 디바이스드라이버이겠는가? 이 책을 읽는 독자라면, 아마 디바이스드라이버라고 대답할 것이다. 그렇다면 응용프로그램을 보다 더 전문가에게 맡기고, 당신은 디바이스드라이버만을 만들기 위해서는 일반인들이 자신이 만든 응용프로그램이 당신의 디바이스드라이버와 통신하는 환경을 만들어야 할 것이다. 이런 경우에 응용프로그램과 디바이스드라이버는 특정 인터패이스를 가지는 경우를 가정해보자. 인터패이스 계층이 존재하게 되면, 응용프로그램개발자는 이런 인터패이스에 맞추어서 자신의 프로그램을 만들게 되며, 디바이스드라이버 역시 인터패이스에 맞추어서 자신의 디바이스드라이버프로그램을 만들게 된다.
인터패이스를 가지게 됨으로써, 보다 확장성 있는 응용프로그램과 디바이스드라이버가 만들어질 수 있을 것이다.
이제, 조금 더 깊숙히 들어가보자. 이제 당신이 선택한 디바이스드라이버는 응용프로그램적인 요소는 완전히 제거되었다. 그런데, USB이동식디스크를 PC에 연결한다는 것은 사실 PC가 가진 USB HostController라는 장치가 제공하는 허브(HUB)에 이 이동식디스크를 연결한다는 의미이다. 그러므로, 디바이스드라이버가 이동식디스크를 관리하기 위해서라면, 필수적으로 PC에 내장된 USB HostController를 이해할 수 밖에 없다. PC에 내장된 USB HostController가 한가지 종류만 있는 것이 아니다. 크게 2가지의 형태로 시중에 나와 있기때문이다. 하나는 “Universal Host Controller"이며 또 하나는 ”Open Host Controller"이다. 이렇게 서로 다른 “USB HostController"에 대해서 여러분이 만든 USB이동식디스크드라이버는 모두를 고려하고 있어야 한다. , 이런 USB HostController가 사용하는 메인보드의 버스(BUS) ISA BUS인가? 아니면, PCMCIA BUS인가? 그것도 아니면 PCI BUS인가? 해당하는 버스에 연결되어 사용되려면, BUS에 대해서 고려하는 코드 역시 디바이스 드라이버내에서 구현 되어져야 한다. 예를 들어, PCI BUS를 사용하는 경우라면, PCI BUS가 요구하는 적절한 "PlugAndPlay Resource Enumeration"을 해야 한다. 또한, ”PCI Device Start"역시 제공해야 한다. “PCI Device Start"란 의미는 모든 PCI카드는 부팅과 PCIBIOS에 의해서 동작명령즉 Start명령을 받도록 설계되어 있기에, 이런 작업을 "PCI Device Start"라고 부른다. 과연, 당신은 USB이동식디스크를 위한 디바이스드라이버를 만들면서 이 모든 것들을 다 고려할 것인가? 해답은 그렇지 않는 것이 유리하다는 것이다. 꼭 그래야 한다면 할 수 없지만, 이 모든 것을 다 지원한다면 코드의 양은 무척 커지게 될 것이며, 코드의 신뢰도를 확인하는 작업도 만만치 않을 것 이다. 또한 코드의 확장성와 유연성에 있어서도 단점을 가지게 된다. 그런 이유로 인해서 당신이 만들게 되는 USB이동식디스크드라이버역시 몇 가지 부분으로 나뉘어 보다 전문성있는 개발자들이 손을 대는 부분을 염두하게 된다

 

 

결국, 디바이스드라이버라는 영역이 크게 3가지 영역으로 확장 되어진 결과가 되었다.
윈도우즈에서는 이렇게 구분되어서 작성된 디바이스드라이버를 많이 보게 된다
.
윈도우즈에서는 실제로 USB이동식디스크드라이버를 위한 드라이버코드는 크게 4부분으로 나뉘어디스크드라이버”, “USB HUB드라이버”, “USB HostController드라이버”, "PCI Bus드라이버등으로 나뉘게 된다. 이렇게 나뉘어지는 이유는 보다 전문적인 코드모듈을 사용하기 위해서이다. 이런 경우, 4가지의 드라이버들은 하나의 USB이동식디스크드라이버를 운용하기 위해서 함께 동작하는 하나의 모델을 그리게 되는데, 이런 모델을 그리기 위해서는 디바이스 스택(Device Stack)이란 개념이 필요하다.


윈도우즈에서 USB버스를 사용하는 장치는 이동식디스크만 있는 것이 아니라, USB Network카드, USB 카메라장치, USB 오디오 장치등등 많은 장치들이 있다. 따라서, USB이동식디스크드라이버에서 언급한 "USB HUB드라이버“, ”USB HostController드라이버그리고 ”PCI Bus드라이버등은 비단 USB이동식디스크에만 적용되지 않아야 한다. 다른 장치들도 이런 드라이버들이 필요하기 때문이다. 그런 이유에서 디바이스드라이버들은 자기자신이 개입해야 하는 장치들을 위해서 DeviceObject(Device Context)를 만들어서 사용하게 된다.

결국, 모든 드라이버는 자신이 포함 되어질 대상의 논리적인 하나의 디바이스를 위해서 하나의 DeviceObject를 생성하여 포함시키게 된다. 그렇기 때문에, 동일한 USB이동식디스크가 2개 사용되는 PC에서는 우리가 2개의 DeviceObject를 생성 해야 하는 이유가 여기에 있다고 할 수 있다.

이렇게 열거자와 주기능자로서의 역할을 모두 가지고 있는 드라이버들은 내부적으로 2가지의 DeviceObject를 생성하여 관리하고 있다. 이때, 열거자로서의 역할을 수행하는 DeviceObject Physical Device Object라고 부른다. 결국 하나의 논리적인 의미에서 PCI IDE CDROM디바이스를 구성하는 디바이스 스택은 크게는 하나의 DeviceStack이 사용되며, 세부적으로는 3가지의 DeviceStack으로 나뉠 수 있다.

 

 

“AddDevice Routine"함수가 호출되는 이유가 DeviceObject를 생성하라는데 있다고 보았다. 보다 더 정확한 의미에서 호출이유를 정의한다면, 그것은 바로 자신이 속할 DeviceStack을 위해서 필요로 하는 DeviceObject를 생성하라는 의미가 된다. , Physical Device Object(열거자로서의 역할) ”AddDevice Routine"에서 생성하는 것이 아니라는 점을 유념해야 한다. Physical Device Object가 생성되어진 이후에 DeviceStack이 생성되는 것 이기 때문이다. 결국 Physical Device Object가 없으면 디바이스스택자체도 생성될 수 있는 근거가 없는 것이다.

“AddDevice Routine"
함수의 프로토타입을 보자.


NTSTATUS  SAMPLEAddDevice(
         PDRIVER_OBJECT pDriverObject,
         PDEVICE_OBJECT pPhysicalDeviceObject );

파라미터에서 “pDriverObject" ”DriverEntry"함수에서 보았던 우리를 위해서 IOManager가 만들어 놓은 자료구조이다. “pPhysicalDeviceObject” DeviceObject로서, 현재 USB이동식디스크드라이버를 위해서 구축되고 있는 디바이스 스택의 가장 하위 DeviceObject, USB Bus드라이버가 생성한 DeviceObject를 의미한다. “AddDevice Routine"이 호출될 당시, 우리에게는 이처럼 우리가 속할 디바이스 스택 상의 버스드라이버가 생성한 가장하위 DeviceObject에 대한 주소를 넘겨받는다는 것을 알 수 있다.

현재 윈도우즈가 제공하는 디스크드라이버(DISK.SYS) USBHUB열거자(USBHUB.SYS)가 생성하는 PhysicalDeviceObject에 대해서 잘 어울리는(?) 성격을 가지고 있을까? 다시 말하면, 디스크드라이버(DISK.SYS)가 자신이 원할 때 어떤 일을 수행하는데 있어서, USBHUB열거자(USBHUB.SYS)드라이버를 호출하는 것이 자유스러운가 하는 이야기이다. 정답은 그렇지 않다는 것이다. USBHUB가 생성하는 열거자로서의 DeviceObject는 이런일을 하기에 너무 부족하다. USBHUB가 생성하는 열거자로서의 DeviceObject는 이런 USB이동식디스크장치에만 사용되는 것이 아니라, USB버스를 사용하는 거의 모든 USB디바이스에는 다 사용되는 성격을 가지고 있기 때문에 구태여 디스크드라이버를 위한 코드를 담고 있지는 않다는 것이다. 여기서, 우리는 필터드라이버의 역할을 배울수 있다. 지금같이 USBHUB드라이버와 DISK드라이버간의 매끄러운 연결을 지원하기 위해서 필터드라이버가 필요한 것이다
.

디바이스 스택 이란 의미는 여러 개의 DeviceObject들이 어떤 규칙을 가지고 서로 연결되어 있는데, 이런 연결된 DeviceObject가 생성되고 제거되는 순서가 마치 자료구조의 스택(Stack)과 같은 순서대로 이루어진다는 것이다
.

우리가 고려된 USB이동식디스크의 디스크 디바이스 스택이 형성되는 순서는 가장 하위의 USBHUB드라이버가 생성한 PhysicalDeviceObject가 가장 먼저 생성 되어 져야 하고, 그 다음에 우리가 개입하여 FilterDeviceObject를 생성해야 하고, 그 다음에 디스크드라이버가 개입하여 DeviceObject를 생성해야 하는 것이다. 그들간에는 서로 "AttachedDevice"라는 DeviceObject내의 맴버 변수에 의해서 연결되어 있다. 이런 연결된 관계는 후에 해체시기가 되면 역순으로 이루어지는데, 순서는 가장 상위의 디스크드라이버의 DeviceObject가 먼저 제거되고, 그 다음 우리가 개입한 FilterDeviceObject가 제거되고, 마지막으로 USBHUB드라이버가 생성한 PhysicalDeviceObject가 제거된다.


“AddDevice Routine"
이 하는 일은 여기까지이다. 이곳이 호출되는 것은 우리가 앞으로 사용하게 될 하드웨어장치의 문맥(DeviceObject)에 대한 생성과 특정 pPhysicalDeviceObject 로부터 시작된 디바이스 스택 상에 우리의 DeviceObject를 올려놓는일이다. 그렇기 때문에 ”AddDevice Routine" "Add My DeviceObject(Context) To Current Device(Context) Stack"으로 풀어서 설명할 수 있는 것이다. 주의할 점은 이곳 “AddDevice Routine"은 디바이스 스택을 형성하는 루틴이지, 하드웨어장치를 사용하는 루틴이 아니라는 점이다. 결국, USB이동식디스크드라이버를 작성하는 우리 역시, 이곳에서 USB이동식디스크를 사용하는 행동을 해서는 않 된다는 것이다. 디바이스 스택에 대한 더 자세한 내용은 3장에서 배우도록 하자.

[
정리]
AddDevice Routine
은 우리가 지원할 하드웨어장치가 PC에 연결되어 운영체제가 이를 인식하는 시기에 호출되는 루틴으로서, “DriverEntry"와 달리, 같은 종류의 하드웨어장치가 연결되는 횟수에 따라서 그와 같은 횟수로 호출되는 성질을 가진다.
이 곳에서는 우리가 앞으로 사용할 DeviceObject를 생성하여, DeviceObject DeviceStack상에 올려놓는 역할만 수행해야지, 이곳에서 역시 자신의 하드웨어장치를 사용하려는 행동을 해서는 안 된다. 그 이유는 아직 디바이스 스택이 완전히 완성된 것이 아니라, 완성하고 있는 과정 이기 때문이다.
 

 

 

(3) "IRP Dispatch Routine"


이곳은 외부로부터 명령어(IRP)를 받는 곳이다. 명령어(IRP)는 특별한 형식으로 되어 있는데, 이것은 단순한 명령어라고 하기 보다도, Device Stack에 전달되기에 적당한 형식으로 작성되어져 있다는 것이다. 명령어란 대게, 보내는 자와 받는 자와의 일대일 관계를 서술하는 것이 일반적이지만, IRP명령어는 보내는 자는 하나지만, 받는 자가 여러 개의 Device Object로 구성된 Device Stack이라는 점이 특이한 것이다.

일단, 이함수의 프로토타입을 보자.


NTSTATUS SAMPLEPnpDispatch(
       PDEVICE_OBJECT pDeviceObject, PIRP pIrp );

 첫 번째 파라미터인 pDeviceObject는 앞부분에서 서술했던, 우리가 생성한 DeviceObject를 의미한다. 이것을 통해서 2가지 이상의 같은 종류의 하드웨어를 구분하여 프로그래밍할 수 있는 문맥을 삼을 수 있다. 두 번째 파라미터는 명령어, IRP이다.
이 함수는 외부로부터 IRP를 받아드린다는 점에서 중요한 역할을 수행한다. WDM디바이스드라이버가 이런 IRP Dispatch함수를 두지 않으면, 외부로부터 완전히 고립된다는 의미를 가지기도 하기 때문이다. WDM디바이스드라이버가 IRP를 받지 않는다는 것은 현실적으로는 어떤 서비스로 수행하지 못한다는 것을 의미하며, 따라서 그런 드라이버는 실제로 존재가치가 무의미하다
.
따라서, WDM디바이스드라이버가 어떤 DeviceStack에 동참하고 있는 한, 외부로부터 명령어(IRP)를 받는 것은 당연하다고 할 수 있다
.
우리가 형성하고 있는 DeviceStack으로 보내지는 명령어들은 크게 몇 가지로 구분된다
.

IRP
DeviceStack을 사용하려는 외부의 Client는 항상 준비해야 하는 구조체이기도 하다. IRP구조체역시 뒷장에서 자세히 배우므로, 이곳에서는 DeviceStack해체를 수행하는 명령어인 IRP_MJ_PNP(IRP_MN_REMOVE_DEVICE)에 대해서만 살펴보도록 한다.


case  IRP_MN_REMOVE_DEVICE:
 
     IoDetachDevice(ptargetDevice);
      IoDeleteDevice(pDeviceObject);

 

문장을 볼수있는데, 이 문장은 현재 우리가 참여하고 있는 DeviceStack에서 우리를 제거한다는 의미를 가진다.

 

IoDetachDevice()함수는 앞 부분에서 배운 IoAttachDeviceToDeviceStack()함수의 반대역할을 수행하는 함수이다. 이 함수를 사용함으로써 현재 우리와 우리아래에 연결된 DeviceObject와의 연결관계가 끊어진다.

IoDeleteDevice()
함수는 앞 부분에서 배운 IoCreateDevice()함수의 반대역할을 수행한다. 이 함수를 사용함으로써 현재 우리가 생성했던 DeviceObject를 제거한다.

출처 : http://blog.naver.com/netrabbit?Redirect=Log&logNo=20055180390

 

Posted by skensita
Programming/Kernel / Driver2008. 12. 3. 11:55

WDM의 한계


1. WDM 드라이버를 작성하는 것은 로우레벨 작업이고, 복잡하다.

ex> 현재의 WDM 모델에서 드라이버 작성할 때  plug & play, power management 지원하려면,

     최소한 2000라인이 필요

     DDI(Device Driver Interface) 쓰기 어려움

2. DDI가 구식이다.

- 오직 퍼포먼스만을 위해 디자인되었고, 보안이나 사용 편의성이 고려되지 않아있다.

  그래서 DDI는 드라이버들에게 OS의 핵심적인 데이터 구조들을 곧바로 노출!
  →  MS는 이런 구조체들의 변경이 제한될 수 밖에 없었고, 드라이버가 시스템을 크래쉬 시킬 확률 증가!

 

- Versioning 지원이 없다.

3. 미니포트 모델이 너무 많다.

- Windows는 현재 10개 이상의 miniport  Model을 지원.

- 미니포트 모델마다 pnpdhk power management 다루는 방법이 다르다.

4. 멀티펑션 디바이스를 지원하는 작업이 너무 복잡하다.

두가지의 다른 미니포트 모델에 적용되는 멀티펑션 디바이스 지우너위해, 개발자는 WDM 버스 드라이버와 두개의 미니포트 드라이버 작성이 필요

5. 현재 드라이버 모델은 커널 레벨에서만 동작해야 한다.

- WDM과 미니포트 드라이버 모델 → 커널모드에서 실행

커널모드 드라이버는 운영체제의 일부로 대접받게 되므로, 시스템의 가상 메모리 영역 접근권한을 가짐.

이 때문에 커널모드 드라이버에서 에러가 발생하면 바로 시스템을 크래쉬 시키는 BSOD!!

6. 테스트 툴들이 쓰기 어렵다.

 

 

차세대 윈도우즈 드라이버 모델의 디자인 목적

1. 드라이버 모델은 심플하고 유연성(flexible)이 있어야 한다.

 

2. 드라이버 모델은 코어 운영체제 컴퓨넌트와 분리되어야만 한다.

 

3. 드라이버 모델은 일관성이 있어야 한다.

 

4. 드라이버 모델은 확장성이 있어야 한다.

 

5. 드라이버 모��유저모드를 지원해야 한다.

 

6.드라이버 모델은 고급 레벨의 언어를 지원해야 한다.

 

 

WDF(Windows Driver Framework)

* 프레임워크

- 커널모드 드라이버 프레임워크 (KMDF)

 

- 유저모드 드라이버 프레임워크 (UMDF)

- WDF는 Object-oriented, event-driven model을 제공

: Object는 드라이버를 위한 블록을 만드는 것으로 작업을 한다. 드라이버는 이 objects를 미리 정의된 인터페이스들을 통해 수정할 수 있다.

Event 집합은 object의 각각의 종류에 영향을 줄 수 있다. Framework는 각각의 event를 위한 default behavior가 정의되어 있다.
Device-specifice behavior를 위해, 드라이버는 defaults를 재정의할 수 있는 callback routine를 포함하고 있다.

 

- 커널모드 드라이버 프레임워크(Kernel-Mode Driver Framework; KMDF)

커널모드 드라이버를 만드는데 필요한 기본적 기능인 PnP, Power Management, I/O queue, DMA, WMI, synchronization 등 기본적인 기능을 구현, IEEE 1394, USB 같은 주요 버스들에 대한 지원도 한다.

 

운영체제 커널의 일부분으로 포함된 것이 아니라, 별도로 제공되는 독립된 라이브러리이다.

 

커널모드 드라이버 프레임워크에서 인터페이스는 미래에도 가능한 한 드라이버의 독립성을 추구하도록 디자인되어 있다. 만약 드라이버가 크래쉬되면, OS는 시스템을 멈추거나 전체를 크래쉬하지 않고 복구하거나 드라이버엥 의해 할당된 리소스들을 클린업한다.

- 유저모드 드라이버 프레임워크(User-Mode Driver Framework)

Pnp, Power management, 비동기 I/O 지원을 포함하는 커널모드 프레임워크 기능의 일부분을 구현한다.

DMA 수행, 인터럽트 지원, nonpaged 풀 등의 커널모드 리소스를 사용하지 않는 드라이버들은 유저모드에서 실행될 수 있다.

 

네트워크와 연결된 디바이스들(network-connected devices)을 위한 드라이버와 PMP, 카메라, 핸드폰 같은 USB 디바이스들을 위한 드라이버를 만들 수 있다.

 

UMDF는 비스테이서 지원된다. XP에서 지원은 정책결정중이라던데..이부분은 찾아봐야하겠다.

[출처] WDM과 WDF

Posted by skensita