드라이버 개발자를 위한 윈도우 파일 시스템

From YYpBD's MediaWiki

Jump to: navigation, search

지음 : 이병오

(주) 사이버 출판사

목차

파일 시스템 드라이버에 대해서

드라이버 종류

  • 커널 모드 드라이버
  • 유저 모드 드라이버


파일 시스템 드라이버

필터 드라이버

드라이버에 전달되는 I/O 요청을 Hooking해서 조작한다.

  • 파일 시스템 드라이버에서 IRP 흐름
  1. 프로세스가 요청한 작업을 처리하기 위해 IRP를 생성하고 Stack Location을 설정한다.
  2. 필터 드라이버에서 조작할 작업을 처리한다.
  3. IRP Stack을 Stack Location에 복사하고 IRP의 제어를 관리자에게 반환한다.
  4. 필터 드라이버 밑의 드라이버에 IRP를 전달한다.
  5. 파일 시스템 드라이버가 IRP를 처리한다.
  6. 처리한 IRP를 I/O Manager에 반환한다.

드라이버 동기화 메커니즘

  • Spin Lock
  • Dispatcher Object
    • Event Object
    • Timer Object
    • Mutex Object
    • Semaphore Object
  • RESOURCE Object

Spin Lock

IRQL(Interrupt Request Level)에서 실행되는 데이터를 보호하기 위해 사용된다.

여러 개가 동시에 사용되는 경우에는 Deadlock이 발생할 수 있으므로 주의해야한다.

Deadlock을 피하기 위해서는 DDK내의 Driver Verifier를 실행해서 검출이 가능하다.


종류

  • 인터럽트 스핀록

드라이버의 데이터 구조체를 접근할때 데이터 동기화를 목적으로 사용된다.

  • 익스큐티브 스핀록

데이터 구조체를 보호하기 위해 사용된다.

  • 인스택 큐 스핀록

XP에서 정식으로 추가된 것으로 멀티프로세서 환경을 고려한 스핀록이다.


디스패처 오브젝트

이벤트 오브젝트

여러 쓰레드의 실행을 동기화하는 것으로 코드 실행 흐름 제어를 위해 이벤트 발생을 기록한다.

뮤텍스 오브젝트

공유 데이터의 자원을 보호한다.

스핀록과 다른 점은 자원사용을 기다리는 쓰레드의 실행을 Pause시킨다는 점이다.

생성과 해제를 같은 컨텍스트 내에서 해야한다.

세마포어 오브젝트

여러 쓰레드가 공유자원을 동시에 접근하도록 허용한다.

타이머 오브젝트

특정시간을 대기하기 위해 사용한다.

리소스 오브젝트

데이터가 저장된 구조체를 읽기전용으로만 사용할때 이용한다.


기타 동기화 오브젝트

Fast Mutex 오브젝트

Interlocked 연산

ETC

APC : Asynchronous Procedure Call

프로세스와 스레드의 컨텍스트

I/O 관리자

I/O 시스템

WDM WMI 함수, PnP Manager, Power Manager, I/O Manager 등을 관리하는 시스템


I/O 관리자

모든 I/O 요청은 IRP로 구성된다.


  • 파일 이용 절차
  1. 애플리케이션이 WriteFile같은 api를 호출한다. 내부에서는 NtWriteFile 함수를 호출해서 I/O 관리자에게 전달한다.
  2. I/O 관리자는 IRP를 파일 시스템 드라이버에 전달한다.
  3. 파일 시스템 드라이버는 IRP를 논리적인 정보로 변환한후 변경된 정보를 IoCallDriver 함수를 호출하여 IRP 제어를 I/O 관리자에게 전달한다.
  4. I/O 관리자는 적절한 디바이스 드라이버를 호출한다.
  5. 디스크 드라이버는 I/O 관리자에서 전달받은 IRP를 받아 물리위치에 전달한다.

주요 데이터 구조체

  • DRIVER_OBJECT

메모리에 로드된 드라이버에 대한 정보보관 구조체

  1. MajorFunction
  2. DriverExtension
  3. FastIoDispatch

상세 필드는 확인 요망


  • DEVICE_OBJECT

논리, 가상, 물리 장치를 관리하기 위해 커널모드 드라이버가 생성한 구조체


  • IRP

커널모드 드라이버에 I/O 요청을 전달하기 위해 사용한다.


  • VPB

Volume Parameter Block

물리, 가상 디스크의 정보를 표시한다.


  • IO_STATUS_BLOCK

I/O 동작에 관한 결과값 구조체


  • FILE_OBJECT

I/O 관리자가 성공적으로 Open한 파일에 대한 정보 구조체

오브젝트의 선택과 사용

파일 시스템 드라이버가 생성하고 관리해야할 대표적인 오브젝트

  • FCB : File Control Block
  • CCB : Context Control Block

데이터 버퍼에 대해서

I/O 데이터 버퍼의 종류

Direct I/O

드라이버가 Direct I/O 방식을 선택하면 I/O Manager는 데이터 버퍼를 MDL 구조체를 사용하여 나타낸다.

데이터 버퍼가 큰 경우 Buffered 방식보다 효과적이지만 드라이버가 직접 MDL을 처리할 수 있어야 한다.


Buffered I/O

시스템 버퍼를 할당하여 데이터 전송을 처리하는 방식이다.

시스템 영역의 인터미디어트 버퍼를 데이터 버퍼로 사용하며, IRP가 마지막으로 완료되면 시스템 버퍼를 해제한다.

소량의 데이터 전송을 사용하는데 유리하다.


Neither I/O

Direct나 Buffered가 설정되어 있지 않을때 Default로 설정된다.

I/O 관리자는 쓰레드의 가상주소를 드라이버에 제공한다.

데이터 버퍼는 보호되지 않으며, 데이터 복사 과정에서 발생할 수 있는 어떠한 인터미디어트 버퍼링도 없다.

MDL을 생성하거나 데이터를 재복사하지 않으므로 제대로 처리한다면 가장 효율적인 방법이다.


디바이스 I/O 컨트롤 코드

사용자 IOCTL 정의

DeviceType은 드라이버의 종류를 나타낸다.
0x8000 ~ 0xFFFF 범위에서 선택할 수 있다.
Function은 각각의 드라이버에 유일한 값으로 구현하고자 하는 기능이다.
0x800 ~ 0xFFF 에서 선택할 수 있다.
다른 드라이버에서 사용하더라도 무관하게 사용할 수 있다.
Method
Access
 FILE_ANY_ACCESS
 FILE_READ_ACCESS
 FILE_WRITE_ACCESS

CTL_CODE 매크로의 사용

IRP의 처리 과정

IRP에 대하여

어플리케이션이 파일을 여는 과정

  1. 어플리케이션이 파일을 열기 위해 I/O 시스템 서비스를 호출한다.
  2. I/O 관리자는 파일 오브젝트를 위한 Symbolic Link를 얻기 위해 오브젝트 관리자를 호출한다.
  3. 저장된 파일을 나타내는 파일 오브젝트를 찾을 때까지 하나 이상의 파일 시스템을 호출한다.
  4. IRP를 위해 메모리를 할당하고 초기화 과정을 수행한다.
  5. I/O 관리자는 생성된 IRP를 파일 시스템 드라이버에 전달한다.
  6. 파일 시스템 드라이버는 IRP를 처리하고 IoCompleteRequest함수들을 사용하여 I/O 요청을 완료한다.
  7. 드라이버는 IRP 구조체의 I/O Status Block값을 설정하고 IRP를 I/O 관리자에 반환한다.
  8. I/O 관리자는 IRP로부터 I/O Status를 얻고 이 정보를 어플리케이션의 주소공간으로 복사한 후, I/O를 요청한 쓰레드에 전달한다.
  9. I/O 관리자는 처리가 완료된 IRP를 해제한다.
  10. 요청이 성공하면 파일의 핸들을 반환하고 실패하면 적절한 에러코드를 리턴한다.


IRP 처리 방식

  • 순차적인 IRP 처리
  • IRP를 하위 레벨 드라이버에 전달하여 처리
  • 원본 IRP와 관련된 Associated IRP의 처리
  • 새로운 IRP를 생성하여 처리


동기적/비동기적 I/O 처리

IRP가 동기/비동기인지 확인하기 위해서는 IoIsOperationSynchronous 함수로 체크한다.

동기적 I/O 처리 방식

쓰레드나 프로세스가 I/O 요청을 드라이버에 전달한 후 IRP가 완료되기 전까지는 대기명령에 놓이며, I/O가 완료될때까지 다른 I/O 동작을 처리하지 못한다.

비동기적 I/O 처리 방식

쓰레드나 프로세스가 I/O 요청을 드라이버에 전달한 후 IRP가 종료되지 않아도 다른 I/O 요청을 수행하며 전달된 IRP가 완료된 후 중지된 I/O 요청을 다시 수행하는 방식을 말한다.

WriteFile 함수 호출시에 인자로 Overlapped인자가 추가된다.

KeSetEvent로 I/O 요청이 종료되었음을 어플리케이션에게 알린다.


IRP의 할당과 생성

IRP의 할당

IRP 할당 방법

  1. IoAllocateIrp() 호출 : 함수 호출후 IoInitializeIrp()를 호출하면 안된다.
  2. ExAllocatePool() 호출 : 함수 호출후 IoInitializeIrp() 호출 가능. 페이징이 불가능한 영역에 메모리를 할당한다.

IRP의 생성

IRP의 완료 루틴

IRP의 재사용

IRP를 생성하기 위한 함수

DPC에 기반을 둔 I/O 요청

MDL에 기반을 둔 I/O 요청

데이터 읽기 요청

데이터 저장 요청

압축 처리된 I/O 요청

I/O 완료 처리 과정

IRP의 Status와 Information필드에 값을 저장하고 IoCompleteRequest 함수를 호출한다.

I/O 스택

IoGetCurrentIrpStackLocation 함수를 호출해서 IRP 구조체 내에 포함된 스택 로케이션의 포인터를 얻어서 사용한다. 현채 IRP를 처리하고 있는 드라이버의 아래에 위치한 IRP 스택 로케이션은 IoGetNextStackLocation 함수를 호출하여 사용할 수 있다.

IRP 완료 처리를 위한 I/O 스택 설정

IoSetCompletionRoutine으로 완료 루틴을 등록한다.

I/O 관리자의 역할

I/O 요청 완료 과정

완료 루틴의 호출

I/O 요청 취소

I/O 요청 취소 과정

비동기IRP는 Initiated, Pended, Completed 상태로 나눌 수 있다.

I/O 요청 취소 절차

I/O 요청을 지시한 쓰레드가 종료되는 경우이다.

I/O 관리자는 종료된 쓰레드와 관련된 IRP를 제거하기 위해서 IRP를 취소할 수 있는 기능을 제공한다.


쓰레드는 프로세스 관리자가 NtTerminateThread 함수를 호출하여 종료한다.

이때 프로세스 관리자는 I/O 관리자가 제공하는 IoCancelThreadIo 함수를 호출한다.

I/O 관리자는 IrpList 필드에 저장된 각 IRP에 대해 IoCancelIrp 함수를 호출한다.

I/O 요청 취소시 문제점

IRP 처리 규칙

  • IRP를 완료하고자 한다면
  1. IRP의 완료 상태와 정보를 IRP의 I/O Status Block에 채운 다음
  2. IoCompletionRequest를 호출한다.
  3. 드라이버에서 IRP를 완료하는데 사용했던 상태코드를 드라이버의 디스패치 루틴의 리턴값으로 반환해야한다.


  • 드라이버의 디스패치루틴에서 IRP를 종료하지 않고 반환하고 싶다면 반환하기 전에 IoMarkIrpPending을 호출하여 IRP를 완료되지 않은 상태로 표시하고, 드라이버 디스패치 루틴에서 STATUS_PENDING을 반환한다.
  • 드라이버의 디스패치 루틴에서 반환해야할 상태코드가 드라이버의 계층 구조상 현재 IRP를 처리하는 드라이버의 아래에 위치한 드라이버로부터 반환된 상태 코드라면 Irp->PendingReturned 가 나타내는 IRP의 Pending 상태는 완료 루틴에서 전달되어야 한다.
  • 드라이버가 IRP를 위해 완료 루틴을 제공하지 않았다면 I/O 관리자는 드라이버가 정상적으로 동작하도록 위의 방식을 제공한다.

I/O 요청 처리시 주의 사항

  1. 일단 드라이버가 IRP를 받았다면 시스템의 어떤 구성 요소들이라도 동시에 IRP를 억세스할 수 없다. IRP를 다른 커널 모드 드라이버에 전송하거나 IRP를 처리할 때까지는 IRP의 소유 권한은 현재 처리 중인 드라이버가 가지고 있다.
  1. IRP를 다른 드라이버에 전송하거나 처리를 완료했을 때, 드라이버는 IRP를 제어할수 없으며 IRP 필드도 억세스할 수 없다.
  1. IRP의 처리를 종료할 때 호출될 완료 루틴을 설정했다면 추가로 필요한 후처리 과정을 구현한다.
  1. IRP는 한번 이상은 완료될 수 없다.
  1. I/O 처리시는 특정 컨텍스트에서 유효한 리소스를 사용해야 한다.
  1. 커널에서 사용된 버퍼나 데이터들은 사용하는데 주의해야 한다.
  1. 스택 로케이션을 처리하기 위해서는 I/O 관리자가 제공한 억세스 방법을 사용한다.
  1. IoAllocateIrp, IoBuildSynchronousFsdRequest, IoBuildAsynchronousFsdRequest, IoBuildDeviceIoControlRequest, IoMakeAssociateIrp 함수를 사용해서 IRP를 생성해야한다.

가상 메모리 관리자

VMM


프로세스의 주소 공간

  • 커널 모드
  • 유저 모드


커널 영역 가상 주소 공간

0x80000000 운영체제 이미지
0xA0000000 시스템 주소 공간 내에 있는 메모리가 매핑된 View를 위한 영역 (Memory Mapped File)
0xC0000000 ~ 0xC0800000 Hyperspace 영역 
0xC0C00000 ~ 0xC1000000 파일 캐시를 위한 워킹세트 관리
0xC1000000 ~ 0xE1000000 파일 캐시가 사용하는 영역
0xE1000000 ~ 0xFFBE0000 시스템에 있는 페이징이 가능한 영역과 불가능한 영역을 위해 사용
0xFFBE0000 ~ 0XFFC00000 부트 디바이스에 위치한 페이징 파일 위치에 관한 정보를 저장
0xFFC00000 ~ 0xFFFFFFFF HAL 정보 저장

물리 메모리 관리

페이지 프레임과 페이지 프레임 데이터베이스

페이지 교체 알고리즘

Windows 2000에서 사용하는 페이지 교체 알고리즘

  1. LRU
  2. FIFO

섹션 오브젝트

메모리에 매핑된 파일을 설명하기 위해 메모리 관리자가 사용하는 구조체


가상 주소의 변환

메모리 매핑된 파일의 지원

페이징

페이지 오류 처리

파일 시스템 드라이버와의 통신

  • VMM이 파일 시스템 드라이버에 제공하는 기능
  1. 파일 시스템 드라이버를 동적으로 로딩하기 위해서는 VMM의 도움이 필요하다.
  2. 커널모드에서 동작하는 모든 드라이버는 드라이버 로딩시 드라이버를 위한 메모리를 필요로 한다.
  3. 커널 모드 드라이버는 특정 프로세스 컨텍스트에서 실행되는 동안에만 억세스할 수 있기 때문에 VMM은 시스템에 있는 모든 프로세스의 가상 주소 공간을 관리하고 시스템에서 실행되는 모든 프로세스 컨텍스트에 있는 동일한 물리 주소를 매핑해야 한다.
  4. 유저모드의 특정 쓰레드에서 할당하고 전달된 버퍼를 사용하는 경우가 있다.
  5. VMM은 시스템에서 실행중인 모든 쓰레드에 할당된 스택 프레임을 관리한다.
  6. VMM은 파일 시스템과 캐시 관리자가 파일 데이터를 캐싱하는데 도움을 준다.
  7. VMM은 페이지 오류를 처리했을때 클러스터링을 지원하며, 이는 시스템의 성능 개선에 도움을 준다.
  8. 때때로 필터 드라이버는 로컬 파일에 대해서 데이터 캐싱이 필요하거나, 유저 모드와 커널 모드 사이에서 데이터 버퍼를 전송하는 상황이 발생한다.
  9. VMM은 시스템이 제공하는 물리 메모리의 크기를 확인하기 위해서 MmQuerySystemSize 함수를 제공한다.
  • 파일 시스템이 VMM에 제공하는 기능
  1. 페이지 파일은 마운트된 파일 시스템에서 생성하고 관리된다.
  2. 공유된 메모리나 메모리 매핑된 파일을 지원하기 위해 VMM은 파일 시스템의 지원을 필요로 한다.

캐시 관리자

Read-ahead : 데이터를 사용하기 전에 미리 가져와서 메모리에 보관 Write-ahead : 효과적으로 디스크에 저장하기 위해 시스템이 데이터를 사용하지 않을 경우 데이터를 디스크에 저장( Delayed-write)


논리적 블록 캐싱과 가상 블록 캐싱

Logical Block Caching
Virtual Block Caching

캐시 관리자가 제공하는 기능

시스템 전체에 걸친 캐시 기능

저장된 데이터에 대해서 시스템 전체에 일관된 캐시 기능을 제공한다.


미리 읽기 기능

데이터를 가져오는 시간을 줄여 시스템 성능을 향상시킨다.


지연 쓰기 기능

수정된 데이터를 디스크에 한꺼번에 저장함으로써 소량의 데이터에 대해 반복해서 저장하는 오버헤드를 줄인다.


캐시 인터페이스

복사 인터페이스(Copy Interface)

고정 인터페이스(Pin Interface)

파일 시스템의ㅏ 메타 데이터를 캐싱하기 위하여 사용된다.


MDL 인터페이스(MDL Interface)

네트워크 파일 서버용 파일 시스템(Windows의 SRV)에서 사용한다.


데이터 읽기/쓰기 캐싱

데이터 읽기 동작

데이터 저장 동작

주요 데이터 구조체

파일 오브젝트 내의 주요 필드

* FsContext
* SectionObjectPointer
* PrivateCachMap

캐시 맵

버퍼 컨트롤 블록

파일 크기에 대한 고려 사항

가상 주소 컨트롤 블록 배열

공유된 캐시 맵과 독립된 캐시 맵

캐싱의 사용을 위해 필요한 작업

Fast I/O

파일을 열 때 처리하는 작업

캐싱의 종료

I/O 제거 요청

I/O 종료 요청

VMM 및 I/O 관리자와의 통신

VMM과의 통신

I/O 관리자와의 통신

미리 읽기 기능

지연 쓰기 기능

드라이버 작성 필수 예제 Filemon

파일 액세스 제어용 드라이버 개발하기

실시간 암복호화

폴더 숨기기 예제

맞춤검색