System Compleat.

'David Solomon'에 해당되는 글 1건

  1. Nonpaged/Paged pool trace, 2nd 1

Nonpaged/Paged pool trace, 2nd

Techs
( younjin.jeong@gmail.com , 정윤진 )

지난번에 Windows Non Paged Pool 관련 에러를 추적하다가, 끝을 싱겁게 낸 적이 있다.
삽질 하였으나, 추적 실패 ;;  

Non-Paged Pool 관련 에러 추적에 대한 내용은 지난글을 참조 하도록 한다.
 
하지만 최근 불꽃 서핑질을 통하여, simple-talk 의 Ben Lye 씨의 포스팅을 통해 명확한 내용을 알게 되었고, 이를 대충 우리 말로 옮긴 것이 다음의 내용이다.

물론 영어를 더 잘 하시는 분들은, 직접 가셔서 보셔도 된다.  @_@;; 여기.


결과부터 추려 흐름대로 진행 해 보면, 다음과 같다.

----

일반적으로 IIS를 구동하고 있는 웹 서버의 경우, 또는 다른 application server 인 경우와 마찬가지로 non paged pool 에러가 발생하게 되면  시스템은 ICMP Echo ( ping ) 등의 요청에 응답하지만, 실제 페이지를 요청해 보면 페이지 에러, IIS 로그를  살펴 보면 Connection Refused 의 에러가 잔뜩 찍히게 된다.

Non paged pool 에러가 발생했을 경우  시스템 이벤트 로그를 보면, 거의 대부분 event id 2019 ,
"The server was unable to allocate from the system nonpaged pool because the pool was empty"
라는 메세지를 보게 된다.

사용자 삽입 이미지


Non Paged Pool 의 명확한 정의는, 대략 추리면 다음과 같다.
 - 커널에서  Page fault 가 허용되지 않는 상황에서 시스템 드라이버 등의 데이터 저장이 가능해야 하는 메모리 공간 , 즉 커널에서 사용되어 절대로 Paging out 되는 일 없는 영역을 말한다.

이 영역은, Windows 버전 별로 다음과 같은 공간 제약을 가진다.
 - Windows Server 2003 32bit 에서 2기가 이상의 메모리를 가진 시스템은 256MB의 제한.
 - Windows Server 2008 32bit 시스템은 2G 또는 전체 메모리의 75% 의 제한.
 
 - Windows Server 2003 64bit 시스템은 128G 또는 전체 메모리의 45%의 제한.
 - Windows Server 2008 64bit 시스템은 128G 또는 전체 메모리의 75%의 제한.

Pool size 관련 내용은 Mark Russinovich 와 David Solomon씨의 "Windows Internals, 5th Edition"같은 저서 또는 Mark Russinovich 씨의 블로그 를 보면 잘 나와 있다고 한다.


시스템에 다음의 툴을 설치한다.

Debugging Tools for Windows
Process Explorer

Process Explorer 를 실행하고, Options -> Symbol Configuration 을 클릭 후
Dbghelp.dll  파일을 Debugging Tool 이 설치된 디렉토리의 해당 파일로 잡아주고,
Microsoft Symbol Server  를 Symbols path 로 적용한다.

사용자 삽입 이미지


Process Explorer 에서 Ctrl + I 단축키를 누르면 Nonpaged Pool 영역의 확인이 가능하다.

사용자 삽입 이미지


문제가 되는 시스템의 메모리 사용을 주기적으로 모니터링 해 보면, nonpaged pool 영역은
시스템을 재부팅 하기 전까지는 절대 줄어들지 않는 모습을 확인 할 수 있다.  따라서, 이는 커널에서 사용하고 있는 드라이버의 메모리 leak 이며, 가능한 빨리 어떤 드라이버가 문제인지 색출해 내는데 촛점을 맞춰야 한다.  이러한 작업에는 poolmon.exe 와 같은 Memory Pool Monitor 툴이 필요 하며,  이 툴은  Windows Support Tools 에 포함되어 있는 poolmon.exe 를 사용하거나 ( 2003 CD에 포함되어 있음 ) Microsoft Download Center 에서 다운로드가 가능하다.


사용자 삽입 이미지


Poolmon 은 Pool Storage 에 대한 사용량 ( paged & nonpaged ) 과 Pool tag로 분류된 정보를 보여준다.  Pool Tag는 보통 4-Character 로 구성된 문자열이며, 커널 API가 Pool 에 디바이스 드라이버 데이터와 같은 내용을 할당할때 사용 된다.


poolmon.exe 를 실행시키면, 도스시절에 보던 푸르딩딩한 바탕의 하양 글씨에 각종 정보가 나타나 있는데, 여기서 'p' 를 누르면  paged 와 nonpaged pool 을 전환하며 필터링 한다.
'b' 키는 byte 순위에 따른 정렬을, 'd'키는  pool 의 할당 또는 미할당 을 기준으로 필터링 하여 정보를 보여준다.

Nonpaged - Sorted by bytes 설정으로 정렬하면 아래와 같은 내용을 볼 수 있다.

사용자 삽입 이미지

그림을 확인 해 보면, 제일 첫번째 줄에 "ShAp" 가 56 바이트씩 2,187,628 회의 allocation 이 발생했으며 Free가 0 이고 , 이로 인해 122,507,168 바이트의 Non-paged Pool 사용이 발견된다.  이는,  Windows 2003 Server 32bit 기준으로 60%가 넘는 Non paged Pool 영역의 사용이며, 따라서 ShAp Tag를 가지는 드라이버가 leak 의 주범으로 의심 할 수 있다.

kernel API 를 찾았으니, 이제 이 Tag 가 대체 어떤 드라이버인지를 알아 내야 한다.  여기에는 몇가지 방법이 있는데,  처음에 설치한 Debugging Tools for Windows 를 사용해 커널 컴포넌트
나 드라이버를  Debugging tools 디렉토리안에 triage\pooltag.txt  에 Tag 들이 나열 되어 있으므로 찾으면 된다.

만약 tag가 pooltag.txt 파일 안에 없다면, Sysinternal 에서 제공하는 Strings , strings.exe 도구 ( Unix 또는 리눅스 기준으로는, 바이너리 또는 파일 안에 있는 해독 가능한 string 형태의 데이터를 찾아서 표시해 준다. 역자주 ) 를 사용해야 한다.

Tag는 Driver File 안에 명시되어 있으며,  대부분의 윈도우 드라이버들은 %SystemRoot%\System32\drivers 디렉토리에 위치하기 때문에 우리는 strings.exe 를 사용하여 쉽게 드라이버를 찾아 낼 수 있다.

사용자 삽입 이미지

strings * | findstr ShAp  커맨드를 통해, klif.sys 라는 드라이버를 찾아 냈다.


파일을 찾아내게 되면, 우리는 드라이버 제공자를 쉽게 추적 할 수 있으며, 이를 바탕으로 해당 드라이버 제조사에 기술지원의 요청이 가능하다. 

위와 같은 테크닉으로, Event ID 2020으로 발생하는 paged pool 영역에 대한 오류 ( "The server was unable to allocate from the system paged pool because the pool was empty." 도 쉽게 추적 해 낼 수 있다.  차이는 paged 냐 nonpaged 냐의 차이 일 뿐.

정리하면,
 - Paged / Nonpaged 영역 관련 오류인지 시스템 이벤트로그에서 메세지를 확인한다.
 - poolmon.exe 를 사용하여 Driver Tag 를 찾아낸다.
 - pooltag.txt 파일 또는 strings.exe 툴을 사용해 드라이버를 밝혀낸다.
 - 드라이버 제공자에게 연락한다.

위와 같은 방법을 따른다면, 이러한 문제는 더이상 어렵게 느껴지지 않을것이다.

-------
결과부터 말하지만, 결국 검색과 윈도우 pool 영역에 대한 이해의 한계였던 거다.
Ben Lye 씨의 포스팅을 보면서 훅 깨달은 바는, 역시 어느 플랫폼이든 공존하는 툴이 있고 추적의 방법은 이해가 수반된다면 거의 대부분 동일하다는 것이다.

윈도우 커널 관련 서적 보다가 퍼져버려 포기할 뻔 했던 내용에 대해 깔끔하고 명확한 정리를 포스팅 해 주신 Ben Lye 씨에게 심심한 감사를 표한다.


( younjin.jeong@gmail.com , 정윤진 )