Windows Internals

IRP (I/O Request Packet)

방마리 2020. 12. 3. 18:14

I/O 관리자

I/O 관리자는 I/O 시스템의 핵심 부분이며, I/O 요청을 디바이스 드라이버에 전달하는 일관적인 프레임워크나 모델을 정의한다.

 

I/O 시스템은 패킷 구동(packet driven) 방식이다.

 

대부분의 I/O 요청은 I/O 요청을 완전하게 기술하는 정보를 갖는 데이터 구조체인 I/O 요청 패킷(IRP)으로 표현된다.

 

IRP는 한 I/O 시스템 '구성 요소'에서 다른 '구성 요소'로 이동한다.

 

개별 애플리케이션 스레드는 다중 I/O 요청을 동시에 관리하는 것이 가능하게 설계되어 있다.

 

I/O 관리자는 I/O 작업을 나타내는 IRP를 메모리에 생성하며, IRP의 포인터를 해당 드라이버에 전달하고 I/O 명령이 완료될 때 해당 IRP를 해제한다.

 

반면 드라이버는 IRP를 전달받아 IRP가 지정한 작업을 수행한 후 작업을 완료하거나, 다른 드라이버가 추가적인 처리를 할 수 있게 I/O 관리자에게 전달한다.

 

드라이버가 제공하는 단일화된 모듈 인터페이스는 I/O 관리자로 하여금 드라이버의 구조나 세부 사항에 대한 특별한 지식 없이 어떤 드라이버라도 호출할 수 있게 한다.

즉, 운영체제는 모든 I/O 요청을 파일에 접근하는 것처럼 처리한다.

 

드라이버는 가상 파일에 대해 이뤄진 요청을 하드웨어의 특정적인 요청으로 변환한다.

 

일반적인 open, close, read, write 함수 외에도, 윈도우 I/O 시스템은 비동기 I/O와 다이렉트 I/O, 버퍼드(buffered) I/O, 스캐터/게더(scatter/gather) I/O 등과 같은 향상된 여러 기능을 제공한다.

 

 

전형적인 I/O 처리

일반적인 I/O 요청은 I/O와 관련된 함수(예를 들어 장치에서 데이터 읽기)를 실행하는 애플리케이션으로부터 시작되고, I/O 관리자와 하나 이상의 디바이스 드라이버, HAL에 의해 처리된다.

 

앞에서 언급한 것처럼 윈도우에서 스레드는 가상 파일을 상대로 I/O를 수행한다.

 

가상 파일이란 파일처런 취급되는 I/O의 대상(장치나 파일, 디렉터리, 파이프, 메일 슬롯 등)을 일컫는다.

 

일반적인 유저 모드 클라이언트는 CreateFile 또는 CreateFile2 함수를 호출하여 가상 파일에 대한 핸들을 구한다.

함수명으로 인해 조금 오해의 소지를 가지는데, 이들 함수는 파일만을 대상으로 하는 것이 아니라 "GLOBAL??"로 불리는 객체 관리자의 디렉터리 내의 심볼릭 링크(symbolic linc)로 알려진 무엇이든 그 대상이 될 수 있다.

 

CreateFile* 함수의 File 접미어는 이들 함수의 호출 결과로 익스큐티브에 의해 생성된 주체인, "가상 파일 객체(FILE_OBJECT)"를 실제로 의미한다.

 

Sysinternals의 WinObj 툴로 "GLOBAL??" 디렉터리를 보면, C:와 같은 드라이브 이름은 단지 객체 관리자 Device 디렉터리 아래에 있는 내부 이름에 대한 심볼릭 링크(예를 들어 "\Device\HarddiskVolume7")다.

 

"GLOBAL??" 디렉터리 내의 모든 이름은 CreateFile(2)에 대한 인자의 후보가 될 수 있다.

디바이스 드라이버와 같은 커널 모드 클라이언트는 가상 파일에 대한 핸들을 얻기 위해 ZwCreateFile 함수를 사용할 수 있다.

 

"GLOBAL??" 객체 관리자 디렉터리는 종종 예전 이름인 DosDevices로 불린다.
객체 관리자 네임스페이스의 루트에 "GLOBAL??"에 대한 심볼릭 링크를 정의하고 있기 때문에, DosDevices는 여전히 작동한다.
드라이버 코드에서 ?? 문자열은 일반적으로 GLOBAL?? 디렉터리를 참조하는 데 사용된다.

 

 

운영체제는 모든 I/O 요청을 가상 파일에서 동작하는 것처럼 추상화한다.

I/O 관리자는 파일 이외의 I/O에 대해서는 전혀 이해를 못하기 때문이다.

 

따라서 파일 지향적인 명령(open, close, read, write)을 장치 종속적인 명령으로 변환하는 것은 드라이버의 책임이다.

 

따라서, 이런 추상화는 장치에 대한 애플리케이션의 인터페이스를 일반화한다.

유저모드 애플리케이션이 문서화된 함수를 호출하면 파일로부터 읽기와 파일에 쓰기, 기타 작업 등을 수행하기 위해 내부 I/O 시스템 함수가 호출된다.

I/O 관리자는 이런 가상 파일의 요청을 적합한 디바이스 드라이버에 동적으로 전달한다.

 

그림 6-3은 전형적이 I/O 읽기 요청 흐름의 기본 구조를 보여준다.

쓰기와 같은 I/O 요청 유형도 다른 API를 사용할 뿐 유사한 흐름을 가진다.

 

 

Fast I/O (패스트 I/O)?

패스트 I/O는 I/O 시스템이 I/O 요청을 완료하기 위해 IRP를 생성하는 것을 건너뛰고, 대신 드라이버 스택으로 직접 전근하게 하는 특별한 매커니즘이다.
IRP를 사용할 때의 느린 특정 I/O 경로를 최적화하기 위해 이 매커니즘을 사용한다.
드라이버는 자신의 패스트 I/O 진입점을 드라이버 객체의 PFAST_IO_DISPATCH 포인터가 가리키는 구조체에 등록한다.