본문 바로가기

reversing/Windows Driver

Buffered I/O

SMALL

Buffered I/O 방식



운영체제는 유저의 어플리케이션 버퍼와 같은 사이즈의 Non페이지한 시스템 버퍼를 할당한다. 쓰기 작업이 발생할 때는 


드라이버 스택을 호출하기 전에 I/O 관리자는 유저의 데이터를 시스템 버퍼에 복사한다. 읽기 작업이 발생할 때는 


드라이버 스택의 요청 작업이 완료된 후 시스템 버퍼를 유저 영역에 복사 한다



즉, 유저 영역의 데이터를 드라이버의 버퍼로 가져올 때, 드라이버 스택 전에 복사를 마친후 호출한다 


[유저 -> 시스템 버퍼(IRP)]


반면에 시스템 드라이버의 버퍼에서 유저 영역의 버퍼로 데이터를 복사할 때는 드라이버에서의 활동이 모두 마친 후, 유저 영역의 데이터로 복사


[시스템 버퍼-> 유저]




서비스와 상호 동작하거나 느린 디바이스 또는 한번에 상대적으로 적은 양의 데이터를 주고받는 드라이버의 경우에 


buffered I/O 전송 방식을 사용한다. 작은양의 buffered I/O 방식을 사용하면 상호 동작하는 전송에 있어서 적은 양의 물리 메모리를


소비해도 가능하다. 그 이유는 메모리 관리자는 이 buffed I/O 방식을 위해서 매번 통신 할 때 마다 할당된 메모리를  락(lock)할 필요가 없다.


direct I/O 방식과는 다르게 위와 같은 장점이 있다. 일반적으로 비디오, 키보드 마우스, 가상 드라이버들이 buffered I/O 방식을 사용



요약 : 데이터를 전달 할 때마다 페이지를 할당하고 lock(해당 데이터 전달을 위해서 메모리를 묶어 놓는 방식)하지 않고 


  적은양의 데이터 송/수신에 사용한다.



I/O Manager는 아래와 같은 상황일 때 I/O 작동이 buffered I/O 방식을 사용한다고 함.


- IRP_MJ_READ, IRP_MJ_WRITE 요청에 대해서 Device Object에서의 flag인 DO_BUFFERED_IO


   설정되어 있을 때 buffered I/O 방식 사용



- IRP_MJ_DEVICE_CONTROL 과 IRP_MJ_INTERNAL_DEVICE_CONTROL 요청에 대해서 IOCTL의 전송 타입


   METHOD_BUFFERED일 때 buffered I/O 방식 사용



아래 설명하는 내용은 IRP_MJ_READ 요청에 대해서 설명하는 내용이다.





위의 그림은 Read 요청에 관해서 드라이버가 IRP에 존재하는 SytemBuffer를 이용해서 어떻게 데이터를 전송하는지 보여준다.


위의 드라이버가 생성한 디바이스 오브젝트의 Flag의 값은 DO_BUFFERED_IO이다.



1.  유저 영역의 가상 메모리는 현재의 스레드 버퍼를 가지고 있을 것이다.  해당 스레드 버퍼의 데이터일 경우 


     페이징 기반 물리 주소의 범위 내에 존재할 것이다.


2.  I/O 관리자는 현재 스레드의 읽기 요청을 도와준다(Service). 스레드는 현재 버퍼의 유저 메모리 영역의 주소를 I/O 관리자에게 넘겨준다.


3.  I/O 관리자는 유저가 제공한 버퍼에 접근가능 한지 확인 한 후, ExAllocatePoolWithTag함수를 호출해서 논 페이지한 시스템 버퍼인


     SystemBuffer를 할당한다. 이때 사이즈의 크기는 유저에서의 버퍼 크기와 동일하다.


4.  I/O 관리자는 드라이버에 전송된 IRP가  할당되어 있는 시스템 버퍼에 접근 할 수 있게한다.

     

     [위에서 할당한 시스템 버퍼와 IRP의 System Buffer의 연결 개념]


5. 드라이버는 디바이스에 존재하는 데이터를 시스템 버퍼로 데이터를 읽어 들인다. 해당 시스템 버퍼의 경우


     Non 페이징하고 해당 메모리에 lock 없이 안전하게 접근할 수 있다. 


     그리고 해당 읽기 과정이 끝이 나면, 드라이버는 IRP에 IoCompleteRequet를 호출한다.


6. 이제 유저 영역의 스레드가 동작할 때, I/O 관리자는 시스템 버퍼로부터 유저 버퍼로 데이터를 읽어들인다.


    그리고 ExFreePool 함수를 호출해서 시스템 버퍼를 해체한다.





[출처] https://docs.microsoft.com/en-us/windows-hardware/drivers/kernel/methods-for-accessing-data-buffers

LIST

'reversing > Windows Driver' 카테고리의 다른 글

I/O Control Codes [IOCTL] 정리  (0) 2017.08.09
MDL(Memory Descriptor List)[1]  (1) 2017.08.08
WinDBG 명령어 [CallStack]  (0) 2017.08.08
IRP, I/O Stack 관련 내용 정리 [3]  (0) 2017.08.04
IRP, I/O Stack 관련 내용 정리 [2]  (0) 2017.08.04