PE(Portable Executable) format이란 Win32, Win9x, W2K, WinNT 등 Windows 계열 플랫폼에서 실행파일을 위해 설계된 파일 포맷입니다. 이는 UNIX의 COFF(Common Object File Format)에서 파생된 것으로 실행 코드외에도 리소스, relocation 데이터, 디버깅 정보, DLL import와 export에 관련된 테이블 정보 등을 포함할 수 있습니다. EXE나 DLL 외에도 드라이버 파일, ActiveX 콘트롤 등 모든 실행 파일은 PE format을 따라야 합니다. 프로세스의 가상 메모리 공간에 이러한 PE format file은 memory mapped file 기술을 이용해서 메모리로 로드되어 바로 실행될 수 있는 형태로 구성되어 있습니다.

Windows 운영체제는 실행파일에 따라서 어떠한 환경의 subsystem에서 실행되어야 하는지 판단하고 해당 플랫폼에서 실행될 수 있도록 환경을 구성해줍니다. 예를 들어 Windows 64bit 환경에서도 WOW64 기술을 이용해서 기존 x86 기반의 32bit 어플리케이션도 실행될 수 있으며, MSDOS 응용프로그램도 VDM(Virtual DOS Machine) 위에서 실행될 수 있습니다. 뿐만 아니라 POSIX 프로그램도 Windows 운영체제에서 실행될 수 있습니다. 이는 프로그램이 실행되는 시점에 Windows가 해당 응용프로그램의 PE format에 기록된 정보를 읽어서 어떠한 환경에서 실행되도록 빌드된 응용 프로그램인지 판단하고 이와 적절한 subsystem과 실행 환경을 만들어주기 때문입니다.

이처럼 실행 파일의 실행에 필요한 정보를 파일 내부에 직접 가지고 있으므로 이동이 가능하고(portable) 또한 실행이 가능(executable)합니다.

 PE format의 내부 구조에 대해서는 다음에 기회가 있으면 보다 자세히 다루도록 하고, 오늘은 PE 파일의 내부 구조를 분석해서 보여주는 툴을 통해서 어떠한 정보가 포함되어 있는지 대략 살펴보도록 하겠습니다. PE format을 보여주는 많은 툴 중에서 freeware로 사용할 수 있는 PE Viewer v1.0을 이용해서 Windows 운영체제에 기본으로 탑재된 notepad.exe 실행파일을 살펴보도록 하겠습니다.

PE Viewer v1.0
http://www.softpedia.com/get/Programming/Other-Programming-Files/PE-Viewer.shtml

--------------------------- 이하 PEVIEWER의 Misc 탭의 내용 ---------------------------------

File: C:\WINDOWS\NOTEPAD.EXE Size 10E00 (69120 bytes 67 KB)    <-- 실행파일의 크기
PE base is   E0

--->Following is IMAGE_FILE_HEADER

Offset : 00000004 Machine : 014C Intel i386   // 파일이 샐행될 CPU 플랫폼
Offset : 00000006 NumberOfSections :    3    // 섹션의 개수
Offset : 00000008 TimeDateStamp : 41107CC3    // 파일이 생성된 시간과 날짜
Offset : 0000000C PointerToSymbolTable : 00000000    // 디버깅시 사용되는 심볼 테이블의 위치
Offset : 00000010 NumberOfSymbols : 00000000   // 디버깅시 사용되는 심볼의 개수
Offset : 00000014 SizeOfOptionalHeader : 00E0   // OptionalHeader의 크기
Offset : 00000016 Characteristics : 010F No relocation. Executable. Line number stripped. Local symbols stripped. 32 bits word machine. // exe인지 dll인지 식별하는데 사용되는 플래그

--->Following is IMAGE_OPTIONAL_HEADER

Offset : 00000018 Magic : 010B
Offset : 0000001A LinkerVersion :  7.10   // Liker 버전
Offset : 0000001C SizeOfCode : 00007800
Offset : 00000020 SizeOfInitializedData : 0000A600
Offset : 00000024 SizeOfUninitializedData : 00000000
Offset : 00000028 AddressOfEntryPoint (RVA) : 0000739D   // PE 파일에서 처음 실행될 명령의 RVA 주소
Offset : 0000002C BaseOfCode (RVA) : 00001000
Offset : 00000030 BaseOfData (RVA) : 00009000
Offset : 00000034 ImageBase (RVA) : 01000000   // PE 파일 로딩시 선호되는 시작 주소
Offset : 00000038 SectionAlignment : 00001000   // 각 섹션은 4096의 배수가 되는 곳에서 시작되어야 함
Offset : 0000003C FileAlignment : 00000200 
Offset : 00000040 OperatingSystemVersion : 5.1
Offset : 00000044 ImageVersion : 5.1
Offset : 00000048 SubsystemVersion : 4.0
Offset : 0000004C Reserved1 : 00000000
Offset : 00000050 SizeOfImage : 00014000     // 메모리에 로딩될 PE 이미지의 전체 크기
Offset : 00000054 SizeOfHeaders : 00000400   // PE Header의 크기
Offset : 00000058 CheckSum : 00014F7F (Correct checksum is 00014F7F)
Offset : 0000005C Subsystem : 0002 WINDOWS_GUI (Graphics)
Offset : 0000005E DllCharacteristics : 8000
Offset : 00000060 SizeOfStackReserve : 00040000  
Offset : 00000064 SizeOfStackCommit : 00011000  
Offset : 00000068 SizeOfHeapReserve : 00100000
Offset : 0000006C SizeOfHeapCommit : 00001000
Offset : 00000070 LoaderFlags : 00000000
Offset : 00000074 NumberOfRvaAndSizes : 00000010


 ~~~~IMAGE_DATA_DIRECTORY~~~~
 Offset : 00000078 01  RVA : 00000000  Size : 00000000 Name : Export
 Offset : 00000080 02  RVA : 00007604  Size : 000000C8 Name : Import
 Offset : 00000088 03  RVA : 0000B000  Size : 00008958 Name : Resource
 Offset : 00000090 04  RVA : 00000000  Size : 00000000 Name : Exception
 Offset : 00000098 05  RVA : 00000000  Size : 00000000 Name : Security
 Offset : 000000A0 06  RVA : 00000000  Size : 00000000 Name : BaseRelocate
 Offset : 000000A8 07  RVA : 00001350  Size : 0000001C Name : Debug
 Offset : 000000B0 08  RVA : 00000000  Size : 00000000 Name : Architecture
 Offset : 000000B8 09  RVA : 00000000  Size : 00000000 Name : GlobalPtr
 Offset : 000000C0 10  RVA : 00000000  Size : 00000000 Name : TLS
 Offset : 000000C8 11  RVA : 000018A8  Size : 00000040 Name : LoadConfig
 Offset : 000000D0 12  RVA : 00000250  Size : 000000D0 Name : Bound
 Offset : 000000D8 13  RVA : 00001000  Size : 00000348 Name : ImportAddress
 Offset : 000000E0 14  RVA : 00000000  Size : 00000000 Name : DelayLoadImport
 Offset : 000000E8 15  RVA : 00000000  Size : 00000000 Name : COM
 Offset : 000000F0 16  RVA : 00000000  Size : 00000000 Name : Reserved

--->Following is Section Table

Section 1
 Offset : 000000F8 Name : .text   // 실행 코드가 위치한 섹션
 Offset : 00000100 VirtualSize : 00007748   VirtualAddress : 00001000
 Offset : 00000108 SizeOfRawData : 00007800  PointerToRawData : 00000400
 Offset : 00000110 PointerToRelocations : 00000000 PointerToLinenumbers : 00000000
 Offset : 00000118 NumberOfRelocations : 00000000 NumberOfLinenumbers : 00000000
 Offset : 0000011C Characteristics : 60000020


Section 2
 Offset : 00000120 Name : .data  // 데이터 섹션
 Offset : 00000128 VirtualSize : 00001BA8   VirtualAddress : 00009000
 Offset : 00000130 SizeOfRawData : 00000800  PointerToRawData : 00007C00
 Offset : 00000138 PointerToRelocations : 00000000 PointerToLinenumbers : 00000000
 Offset : 00000140 NumberOfRelocations : 00000000 NumberOfLinenumbers : 00000000
 Offset : 00000144 Characteristics : C0000040


Section 3
 Offset : 00000148 Name : .rsrc   // 리소스 섹션
 Offset : 00000150 VirtualSize : 00008958   VirtualAddress : 0000B000
 Offset : 00000158 SizeOfRawData : 00008A00  PointerToRawData : 00008400
 Offset : 00000160 PointerToRelocations : 00000000 PointerToLinenumbers : 00000000
 Offset : 00000168 NumberOfRelocations : 00000000 NumberOfLinenumbers : 00000000
 Offset : 0000016C Characteristics : 40000040
  Physical image size is 00010E00

--->Following is import table   // import table (동적으로 로딩해야 하는 DLL 및 API 리스트)

Offset : 00006924 Characteristics : 00007990
Offset : 00006928 TimeDateStamp : FFFFFFFF
Offset : 0000692C ForwarderChain : FFFFFFFF
Offset : 00006930 Name RVA: 00007AAC Name : comdlg32.dll
Offset : 00006934 FirstThunk : 000012C4
 Ordinal : 000F  Name : PageSetupDlgW
 Ordinal : 0006  Name : FindTextW
 Ordinal : 0012  Name : PrintDlgExW
 Ordinal : 0003  Name : ChooseFontW
 Ordinal : 0008  Name : GetFileTitleW
 Ordinal : 000A  Name : GetOpenFileNameW
 Ordinal : 0015  Name : ReplaceTextW
 Ordinal : 0004  Name : CommDlgExtendedError
 Ordinal : 000C  Name : GetSaveFileNameW

Offset : 00006938 Characteristics : 00007840
Offset : 0000693C TimeDateStamp : FFFFFFFF
Offset : 00006940 ForwarderChain : FFFFFFFF
Offset : 00006944 Name RVA: 00007AFA Name : SHELL32.dll
Offset : 00006948 FirstThunk : 00001174
 Ordinal : 001F  Name : DragFinish
 Ordinal : 0023  Name : DragQueryFileW
 Ordinal : 001E  Name : DragAcceptFiles
 Ordinal : 0103  Name : ShellAboutW

Offset : 0000694C Characteristics : 00007980
Offset : 00006950 TimeDateStamp : FFFFFFFF
Offset : 00006954 ForwarderChain : FFFFFFFF
Offset : 00006958 Name RVA: 00007B3A Name : WINSPOOL.DRV
Offset : 0000695C FirstThunk : 000012B4
 Ordinal : 0078  Name : GetPrinterDriverW
 Ordinal : 001B  Name : ClosePrinter
 Ordinal : 007E  Name : OpenPrinterW

Offset : 00006960 Characteristics : 000076EC
Offset : 00006964 TimeDateStamp : FFFFFFFF
Offset : 00006968 ForwarderChain : FFFFFFFF
Offset : 0000696C Name RVA: 00007B5E Name : COMCTL32.dll
Offset : 00006970 FirstThunk : 00001020
 Ordinal : 0008  Name : CreateStatusWindowW

Offset : 00006974 Characteristics : 000079B8
Offset : 00006978 TimeDateStamp : FFFFFFFF
Offset : 0000697C ForwarderChain : FFFFFFFF
Offset : 00006980 Name RVA: 00007C76 Name : msvcrt.dll
Offset : 00006984 FirstThunk : 000012EC
 Ordinal : 004E  Name : _XcptFilter
 Ordinal : 00F6  Name : _exit
 Ordinal : 00C5  Name : _c_exit
 Ordinal : 0317  Name : time
 Ordinal : 02D4  Name : localtime
 Ordinal : 00C8  Name : _cexit
 Ordinal : 02C6  Name : iswctype
 Ordinal : 00ED  Name : _except_handler3
 Ordinal : 0274  Name : _wtol
 Ordinal : 032F  Name : wcsncmp
 Ordinal : 01E4  Name : _snwprintf
 Ordinal : 0290  Name : exit
 Ordinal : 00A8  Name : _acmdln
 Ordinal : 006D  Name : __getmainargs
 Ordinal : 013B  Name : _initterm
 Ordinal : 009A  Name : __setusermatherr
 Ordinal : 00B6  Name : _adjust_fdiv
 Ordinal : 0080  Name : __p__commode
 Ordinal : 0085  Name : __p__fmode
 Ordinal : 0098  Name : __set_app_type
 Ordinal : 00D6  Name : _controlfp
 Ordinal : 0330  Name : wcsncpy

Offset : 00006988 Characteristics : 000076CC
Offset : 0000698C TimeDateStamp : FFFFFFFF
Offset : 00006990 ForwarderChain : FFFFFFFF
Offset : 00006994 Name RVA: 00007D08 Name : ADVAPI32.dll
Offset : 00006998 FirstThunk : 00001000
 Ordinal : 01EE  Name : RegQueryValueExW
 Ordinal : 01CA  Name : RegCloseKey
 Ordinal : 01D0  Name : RegCreateKeyW
 Ordinal : 0139  Name : IsTextUnicode
 Ordinal : 01ED  Name : RegQueryValueExA
 Ordinal : 01E3  Name : RegOpenKeyExA
 Ordinal : 01FB  Name : RegSetValueExW

Offset : 0000699C Characteristics : 00007758
Offset : 000069A0 TimeDateStamp : FFFFFFFF
Offset : 000069A4 ForwarderChain : FFFFFFFF
Offset : 000069A8 Name RVA: 000080EC Name : KERNEL32.dll
Offset : 000069AC FirstThunk : 0000108C
 Ordinal : 013E  Name : GetCurrentThreadId
 Ordinal : 01D1  Name : GetTickCount
 Ordinal : 0291  Name : QueryPerformanceCounter
 Ordinal : 016A  Name : GetLocalTime
 Ordinal : 01D5  Name : GetUserDefaultLCID
 Ordinal : 0140  Name : GetDateFormatW
 Ordinal : 01D3  Name : GetTimeFormatW
 Ordinal : 01F5  Name : GlobalLock
 Ordinal : 01FC  Name : GlobalUnlock
 Ordinal : 015A  Name : GetFileInformationByHandle
 Ordinal : 0051  Name : CreateFileMappingW
 Ordinal : 01BD  Name : GetSystemTimeAsFileTime
 Ordinal : 0346  Name : TerminateProcess
 Ordinal : 013B  Name : GetCurrentProcess
 Ordinal : 0332  Name : SetUnhandledExceptionFilter
 Ordinal : 0241  Name : LoadLibraryA
 Ordinal : 0175  Name : GetModuleHandleA
 Ordinal : 01AC  Name : GetStartupInfoA
 Ordinal : 01F1  Name : GlobalFree
 Ordinal : 016C  Name : GetLocaleInfoW
 Ordinal : 024B  Name : LocalFree
 Ordinal : 0247  Name : LocalAlloc
 Ordinal : 03B4  Name : lstrlenW
 Ordinal : 0251  Name : LocalUnlock
 Ordinal : 0038  Name : CompareStringW
 Ordinal : 024D  Name : LocalLock
 Ordinal : 00EA  Name : FoldStringW
 Ordinal : 0031  Name : CloseHandle
 Ordinal : 03AE  Name : lstrcpyW
 Ordinal : 02A3  Name : ReadFile
 Ordinal : 0052  Name : CreateFileW
 Ordinal : 03AB  Name : lstrcmpiW
 Ordinal : 013C  Name : GetCurrentProcessId
 Ordinal : 0197  Name : GetProcAddress
 Ordinal : 010A  Name : GetCommandLineW
 Ordinal : 03A5  Name : lstrcatW
 Ordinal : 00CC  Name : FindClose
 Ordinal : 00D3  Name : FindFirstFileW
 Ordinal : 0159  Name : GetFileAttributesW
 Ordinal : 03A8  Name : lstrcmpW
 Ordinal : 0263  Name : MulDiv
 Ordinal : 03B1  Name : lstrcpynW
 Ordinal : 0250  Name : LocalSize
 Ordinal : 0168  Name : GetLastError
 Ordinal : 038B  Name : WriteFile
 Ordinal : 0313  Name : SetLastError
 Ordinal : 037E  Name : WideCharToMultiByte
 Ordinal : 024E  Name : LocalReAlloc
 Ordinal : 00EC  Name : FormatMessageW
 Ordinal : 01D7  Name : GetUserDefaultUILanguage
 Ordinal : 02FD  Name : SetEndOfFile
 Ordinal : 0082  Name : DeleteFileW
 Ordinal : 00F6  Name : GetACP
 Ordinal : 035A  Name : UnmapViewOfFile
 Ordinal : 0264  Name : MultiByteToWideChar
 Ordinal : 0257  Name : MapViewOfFile
 Ordinal : 0357  Name : UnhandledExceptionFilter

Offset : 000069B0 Characteristics : 000076F4
Offset : 000069B4 TimeDateStamp : FFFFFFFF
Offset : 000069B8 ForwarderChain : FFFFFFFF
Offset : 000069BC Name RVA: 0000825E Name : GDI32.dll
Offset : 000069C0 FirstThunk : 00001028
 Ordinal : 0098  Name : EndPage
 Ordinal : 0000  Name : AbortDoc
 Ordinal : 0096  Name : EndDoc
 Ordinal : 008C  Name : DeleteDC
 Ordinal : 0248  Name : StartPage
 Ordinal : 01B5  Name : GetTextExtentPoint32W
 Ordinal : 002F  Name : CreateDCW
 Ordinal : 0210  Name : SetAbortProc
 Ordinal : 01BB  Name : GetTextFaceW
 Ordinal : 024F  Name : TextOutW
 Ordinal : 0246  Name : StartDocW
 Ordinal : 00CE  Name : EnumFontsW
 Ordinal : 01A5  Name : GetStockObject
 Ordinal : 0197  Name : GetObjectW
 Ordinal : 016B  Name : GetDeviceCaps
 Ordinal : 003D  Name : CreateFontIndirectW
 Ordinal : 008F  Name : DeleteObject
 Ordinal : 01BD  Name : GetTextMetricsW
 Ordinal : 0216  Name : SetBkMode
 Ordinal : 01CB  Name : LPtoDP
 Ordinal : 0242  Name : SetWindowExtEx
 Ordinal : 023E  Name : SetViewportExtEx
 Ordinal : 022B  Name : SetMapMode
 Ordinal : 020E  Name : SelectObject

Offset : 000069C4 Characteristics : 00007854
Offset : 000069C8 TimeDateStamp : FFFFFFFF
Offset : 000069CC ForwarderChain : FFFFFFFF
Offset : 000069D0 Name RVA: 0000873C Name : USER32.dll
Offset : 000069D4 FirstThunk : 00001188
 Ordinal : 00FF  Name : GetClientRect
 Ordinal : 024D  Name : SetCursor
 Ordinal : 022A  Name : ReleaseDC
 Ordinal : 010C  Name : GetDC
 Ordinal : 009F  Name : DialogBoxParamW
 Ordinal : 0243  Name : SetActiveWindow
 Ordinal : 0122  Name : GetKeyboardLayout
 Ordinal : 008F  Name : DefWindowProcW
 Ordinal : 0099  Name : DestroyWindow
 Ordinal : 01DB  Name : MessageBeep
 Ordinal : 0292  Name : ShowWindow
 Ordinal : 0117  Name : GetForegroundWindow
 Ordinal : 01A6  Name : IsIconic
 Ordinal : 0173  Name : GetWindowPlacement
 Ordinal : 0037  Name : CharUpperW
 Ordinal : 01C9  Name : LoadStringW
 Ordinal : 01B4  Name : LoadAcceleratorsW
 Ordinal : 015C  Name : GetSystemMenu
 Ordinal : 0218  Name : RegisterClassExW
 Ordinal : 01BE  Name : LoadImageW
 Ordinal : 01BA  Name : LoadCursorW
 Ordinal : 0282  Name : SetWindowPlacement
 Ordinal : 0061  Name : CreateWindowExW
 Ordinal : 010E  Name : GetDesktopWindow
 Ordinal : 0116  Name : GetFocus
 Ordinal : 01BC  Name : LoadIconW
 Ordinal : 0287  Name : SetWindowTextW
 Ordinal : 0201  Name : PostQuitMessage
 Ordinal : 0228  Name : RegisterWindowMessageW
 Ordinal : 02BB  Name : UpdateWindow
 Ordinal : 026F  Name : SetScrollPos
 Ordinal : 0029  Name : CharLowerW
 Ordinal : 01FE  Name : PeekMessageW
 Ordinal : 00C4  Name : EnableWindow
 Ordinal : 00BE  Name : DrawTextExW
 Ordinal : 0056  Name : CreateDialogParamW
 Ordinal : 017A  Name : GetWindowTextW
 Ordinal : 015D  Name : GetSystemMetrics
 Ordinal : 01E9  Name : MoveWindow
 Ordinal : 0193  Name : InvalidateRect
 Ordinal : 02D3  Name : WinHelpW
 Ordinal : 0110  Name : GetDlgCtrlID
 Ordinal : 003C  Name : ChildWindowFromPoint
 Ordinal : 0231  Name : ScreenToClient
 Ordinal : 010B  Name : GetCursorPos
 Ordinal : 0237  Name : SendDlgItemMessageW
 Ordinal : 0240  Name : SendMessageW
 Ordinal : 002C  Name : CharNextW
 Ordinal : 0039  Name : CheckMenuItem
 Ordinal : 0042  Name : CloseClipboard
 Ordinal : 019F  Name : IsClipboardFormatAvailable
 Ordinal : 01F3  Name : OpenClipboard
 Ordinal : 0137  Name : GetMenuState
 Ordinal : 00C2  Name : EnableMenuItem
 Ordinal : 0159  Name : GetSubMenu
 Ordinal : 012C  Name : GetMenu
 Ordinal : 01E3  Name : MessageBoxW
 Ordinal : 0281  Name : SetWindowLongW
 Ordinal : 016F  Name : GetWindowLongW
 Ordinal : 0111  Name : GetDlgItem
 Ordinal : 0256  Name : SetFocus
 Ordinal : 0254  Name : SetDlgItemTextW
 Ordinal : 02D9  Name : wsprintfW
 Ordinal : 0114  Name : GetDlgItemTextW
 Ordinal : 00C6  Name : EndDialog
 Ordinal : 0145  Name : GetParent
 Ordinal : 02AC  Name : UnhookWinEvent
 Ordinal : 00A2  Name : DispatchMessageW
 Ordinal : 02AA  Name : TranslateMessage
 Ordinal : 02A8  Name : TranslateAcceleratorW
 Ordinal : 01A2  Name : IsDialogMessageW
 Ordinal : 0200  Name : PostMessageW
 Ordinal : 013E  Name : GetMessageW
 Ordinal : 027E  Name : SetWinEventHook


There is no Export table  // Export table. 외부로 export 하는 API 리스트 정보

'Programming' 카테고리의 다른 글

응답 없음(Not Responding)  (0) 2009.05.11
I/O Stack Locations  (0) 2009.05.04
Example I/O request - an overview  (0) 2009.04.21
On-demand 메모리 관리  (0) 2009.04.02
Thread States  (0) 2009.03.27
Posted by noenemy
,

WDK 문서 중에서 I/O Request의 전체 과정을 설명하고 있는 문서가 있어서 이를 번역해 보았습니다. 번역하면서 느낀 것은 역시 기술 문서는 원어 그대로 읽고 이해하는 것이 번역된 문장을 보는 것보다 낫다는 생각이 듭니다. 가능하면 의역을 하려 했는데, 부족한 부분이 있거나 원문 내용을 보시려면 아래 문서를 참고하시기 바랍니다.

Example I/O Request - An overview
http://msdn.microsoft.com/en-us/library/ms795837.aspx

다음 그림은 user mode 어플리케이션에서 특정 file을 open하려고 했을 때 이 요청이 어떻게 커널 레벨에서 file system에 까지 전달된 뒤 그 결과 값으로 handle을 돌려 받는 과정을 설명하고 있습니다.


ms795837.2OPENDEV(en-us,MSDN.10).png

  1. Windows subsystem이 특정 이름의 파일을 open 하기 위해 I/O system service를 호출한다.
  2. I/O manager는 해당 파일이 있는지 찾고 해당 file object에 대한 symbolic links를 resolve할 수 있도록 object manager를 호출한다. 또한 subsystem이 해당 file object를 open하는데 필요한 적절한 권한을 가지고 있는지 체크하기 위해 security reference manager를 호출한다.
  3. 해당 volume이 아직 마운트되지 않았다면, I/O manager는 open 요청을 잠시 보류하고 해당 해당 file object가 인식될 때까지 여러 file system을 호출한다. 해당 file system이 마운트되면, I/O manager는 open 요청을 다시 재진행한다.
  4. I/O manager는 open 요청을 위한 IRP를 초기화하고 메모리를 할당한다. 드라이버 입장에서 'open'은 "create" 요청에 해당한다.
  5. I/O manager는 파일 시스템 드라이버를 호출하고 해당 IRP를 전달한다. 파일 시스템 드라이버는 어떠한 명령을 수행해야 하는지 판단하기 위해서 해당 IRP의 I/O stack location에 접근하고, 만약 없다면 해당 IRP의 하위 드라이버의 I/O stack location을 설정한다.
  6. 해당 IRP를 처리하고 요청된 I/O 명령을 complete 하려면 I/O manager나 다른 시스템 구성요소에 의해 제공되는 커널모드 루틴을 호출해야 한다.
  7. 드라이버는 요청한 명령에 대해 성공했거나 또는 실패한 이유를 I/O status block을 set하고 해당 IRP를 I/O manager에게 리턴한다.
  8. I/O manager는 해당 IRP로부터 I/O status 값을 얻고, 이를  subsystem을 통해 최초 호출자에게 상태 값을 리턴할 수 있게 된다.
  9. I/O manager는 completed된 IRP를 해제한다.
  10. I/O manager는 open 명령이 성공했다면 subsystem에게 해당 file object를 위한 handle을 리턴한다. 만약 실패하였다면 subsystem에게 적절한 status를 리턴한다.

Windows subsystem이 특정 파일에 대한 file object를 open 하는데 성공하면, 그 이후에는 read, write, device I/O 요청과 같은 부수적인 요청에는 리턴된 handle을 이용하게 된다. 이런 요청을 처리하기 위해서 subsystem은 I/O sysem services를 호출하고, I/O manager는 이를 처리할 드라이버에게 IRPs 보냄으로써 이러한 요청을 전달한다.


'Programming' 카테고리의 다른 글

I/O Stack Locations  (0) 2009.05.04
PEVIEWER로 살펴보는 notepad.exe  (1) 2009.04.30
On-demand 메모리 관리  (0) 2009.04.02
Thread States  (0) 2009.03.27
Windbg Stack Backtracing 명령어  (0) 2009.03.27
Posted by noenemy
,

오늘은 Windows 운영체제의 메모리 관리 방법에 대한 일반적인 얘기를 조금 나눠볼까 합니다.

이미 많은 분들이 아시다시피 x86 기반의 Windows에서는 각 프로세스별로 4GB의 virtual memory를 사용할 수 있도록 할당을 받습니다. 이 중에서 낮은 2GB의 주소(0x000000~0x7FFFFFFF)에 해당하는 공간이 User Mode 영역이고, 높은 2GB의 주소(0x80000000~0xFFFFFFFF)의 공간은 Kernel 영역에서 사용하게 됩니다. User Mode 영역의 경우 각 프로세스별로 독립적인 공간으로 다른 프로세스와는 전혀 다른 공간을 이용하게 되고, Kernel Mode 영역에 해당하는 2GB의 공간은 프로세스의 구분 없이 공유해서 사용되는 공간입니다.

지금은 하드웨어 기술이 발달해서 실제 개인용 PC에서도 물리적인 메모리를 수 GB 이상 갖춘 컴퓨터를 주변에서 흔히 볼 수 있지만, 이러한 virtual memory 개념이 처음 적용되는 당시만해도 128MB 정도의 메모리를 갖춘 컴퓨터도 흔치 않았던 시절입니다. 논리적으로는 프로세스별로 4GB의 메모리 공간을 사용할 수 있도록 허용하고 있지만, 실제로 이 정도의 공간을 필요로하는 응용 프로그램은 특수한 목적의 프로그램이 아닌 이상 거의 보기가 힘들다고 볼 수 있습니다.

Windows 운영체제는 응용 프로그램 뿐만 아니라 운영체제 자신에게도 메모리 사용에 있어서는 절약정신이 매우 투철한데 이를 간단히 'On-demand'로 관리한다라고 표현할 수 있습니다. 즉, '진짜 필요로 할 때에만 물리적인 메모리를 할당해준다'라고 표현할 수 있겠습니다.

우선 물리적 메모리는 x86 장비의 경우 4Kb 크기를 가지는 페이지(page) 단위로 잘게 나누어져 있는데 이를 응용 프로그램에서 사용하기 위해서는 먼저 VirtualAlloc이나 VirtualAllocEx 라는 API를 이용해서 사용하고자 하는 메모리 양을 운영체제에 알리도록 되어 있습니다. 이때 reserve와 commit이라는 2 단계로 구분해서 진행하게 되는데, reserved memory는 해당 프로세스 내의 쓰레드에 의해서 나중에 이 정도의 공간이 사용될 것이므로 '예약'만 해두는 것을 의미합니다. '예약'된 메모리는 아직 사용될 수는 없으며 실제 사용하려면 reserved 된 영역에 대해서 다시 'commit'을 해야 실제로 해당 프로세스에서 사용할 메모리 영역을 할당받고 사용 할 수 있게 됩니다.

이러한 과정은 마치 비행기의 자리를 예약하는 것에 비유할 수 있을 것입니다. 일반적으로 항공사는 특정 항공편에 대해서 120% 정도로 over booking을 받습니다. 이는 실제로 비행기표를 예약했다가 실제로 이륙하기 전에 예약을 취소하거나 탑승하지 못하는 고객이 있기 때문에 이를 대비해서 미리 예약을 실제 좌석수보다 넘게 받은 다음에, 실제로 탑승 수속(check in)을 하는 시점에 실제 좌석을 할당함으로써 빈 좌석으로 운항되는 것을 최대한 방지하려고 합니다. 비행기 표를 예약(reserve)하는 것과 탑승 수속시(commit)에 실제 좌석을 할당 받는 과정을 이러한 개념으로 이해하시면 조금 도움이 되실 것 같습니다.

그런데 운영체제 내부적으로 조금 더 깊게 들어가보면 commit 한 시점에서도 실제로 해당 프로세스에 물리적인 메모리 공간을 할당해주는 것은 아닙니다. 실제로 메모리에 접근할 수 있게 해주는 것은 그것보다도 더 이후로 미뤄둠으로써 메모리가 낭비되는 것을 한번 더 관리하게 되는데, 이는 commit 된 메모리에 실제로 해당 응용 프로그램에서 접근(access)하려는 시점에서야 물리적인 메모리의 특정 페이지를 사용할 수 있도록 허락해 줍니다.

mamory manager에서 물리적 메모리의 page는 프로세스의 가상 주소와 서로 맵핑 시켜주기 위해서 PTE(Page Table Entry)라는 구조체를 사용하는데, 실제로 이러한 PTE가 생성되어서 물리적 메모리가 mapping 되는 것은 최초로 commit된 영역에 대해서 접근하려는 순간에 이뤄집니다. 내부적으로는 commit된 page를 접근하려는 데 아직 PTE가 생성되지 않은 단계이므로 page fault가 발생하게 됩니다. 이 page fault에 대해서 운영체제는 '아.. 이제 진짜 메모리를 쓰려고 하는구나. 이젠 메모리를 사용할 수 있게 해줘야 겠군. 그럼 이 page를 사용해라'라고 PTE를 만들고 물리적 메모리를 맵핑시켜 줍니다.

물리적인 메모리의 사용을 가능한 뒤로 연기해 둠으로써 시스템의 메모리 자원을 절약하고자 하는 컨셉. 이것이 windows의 on-demand 메모리 관리 컨셉입니다.

'Programming' 카테고리의 다른 글

PEVIEWER로 살펴보는 notepad.exe  (1) 2009.04.30
Example I/O request - an overview  (0) 2009.04.21
Thread States  (0) 2009.03.27
Windbg Stack Backtracing 명령어  (0) 2009.03.27
Intel CPU registers  (0) 2009.03.20
Posted by noenemy
,

Thread States

Programming 2009. 3. 27. 14:54

현재 운영체제를 사용하면서 여러 가지 응용 프로그램을 동시에 사용하고 있습니다. 문서 작성을 하면서 음악을 듣고 인터넷 서핑을 동시에 진행할 수 있습니다. 하지만 CPU에서는 원래 동시에 하나의 작업만을 진행할 수 있는데, 시스템에서 실행되어야 하는 여러 작업들을 thread라는 최소 실행단위로 나누고 이러한 여러 thread를 매우 빠른 속도로 나눠서 실행하면서 마치 동시에 여러 프로그램이 실행되는 듯한 효과를 얻을 수 있는 것입니다. 따라서 thread는 시스템을 구성하는 여러 요소 중에서도 실행과 관련된 매우 중요한 역할을 담당하고 있습니다.

 

이러한 thread 들은 생성되고 실행된 뒤 소멸될 때까지 Initialized, Ready, Standby, Runnign, Waiting, Transition, Terminated, Deferred Ready(2003 이후)와 같은 여러 상태 값을 가지게 됩니다. System Dispatcher에 의해서 여러 thread 들의 상태 값을 관리하고 실행될 thread를 선택하는 과정이 이루어 지는데 내부적으로 매우 복잡한 알고리즘에 의해서 운영되고 있습니다. 여기서는 thread의 상태 값들에 대한 의미를 정리해보도록 하겠습니다.

 

 

 

각 State에 대한 의미

 

l  Ready

n  Thread가 실행되기를 기다리는 상태. Thread dispatcher는 다음에 실행할 thread를 이러한 ready state에 있는 thread list에서 찾게 된다.

n  Ready list에 있는 thread 중에서 Priority가 높은 thread 부터 먼저 실행될 대상이 된다.

 

l  Standby

n  현재 CPU에 의해서 실행 중인 thread 다음에 바로 실행될 수 있도록 선택된 thread이다. CPU당 하나의 thread standby 상태에 있을 수 있으며, 이는 ready state에 있는 여러 thread 중에서 선택된다.

 

l  Running

n  현재 CPU에 의해서 실행 중인 thread이다. 일단 Standby 상태에 있던 thread가 실행 상태가 되면 해당 thread가 실행 될 수 있도록 주어진 기간을 의미하는 퀀텀(quantum) 동안 또는 보다 높은 우선순위의 다른 thread에 의해서 선점(preempted)되기 전까지는 실행 상태를 계속 유지하게 된다. 실행이 완료되면 Ready List에 다시 들어가게 된다.

 

l  Waiting

n  Ready List에 포함되지 않고 대기 상태에 있는 thread를 의미한다. 특정 kernel object signaled 상태가 될 때까지 대기하기 위해서 WaitForSingleObject WaitForMultipleObject API를 호출하면 해당 thread Waiting 상태에 들어가게 되며 Dispatcher에서 관리하는 thread scheduling의 대상에서 제외된다. , waiting 상태에서 깨어나기 전에서 CPU에 의해서 실행되지 않는다.

 

l  Transition

n  Waiting 상태에 있다가 실행될 수 있는 Ready 상태가 되려고 하지만 해당 thread kernel stack page out 된 경우에 해당한다. Kernel stack 영역이 다시 메모리로 page in 되면 비로소 Ready 상태가 된다.

 

l  Terminated

n  특정 thread의 실행이 종료되면 terminated 상태가 된다.

 

l  Initialized

n  Thread가 생성되어 운영체제 내부적으로 초기화하고 있는 과정에 해당한다.

 

참고로 Windows Server 2003 이후 운영체제에서는  시스템이 thread scheduling을 위해서 시스템 전체 범위의 lock을 최소화해서 성능 향상을 도모하고자 위에서 설명한 state 외에 Deferred Ready라는 상태 값이 하나 더 추가 되었습니다.

 

WinDbg에서 !thread 명령어를 이용하면 특정 thread의 state 값을 아래와 같이 확인이 가능합니다.

1: kd> !thread 86c02020
THREAD 86c02020  Cid 0004.0030  Teb: 00000000 Win32Thread: 00000000
RUNNING on processor 1
IRP List:
    a7834eb8: (0006,0148) Flags: 00000000  Mdl: 00000000
Not impersonating
DeviceMap                 83207d08
Owning Process            0       Image:         <Unknown>
Attached Process          86b97720       Image:         System
Wait Start TickCount      107517         Ticks: 0
Context Switch Count      50347            
UserTime                  00:00:00.000
KernelTime                00:00:05.085
Win32 Start Address nt!ExpWorkerThread (0x82078ea7)
Stack Init 83094000 Current 83093570 Base 83094000 Limit 83091000 Call 0
Priority 13 BasePriority 12 PriorityDecrement 0 IoPriority 2 PagePriority 5

 

1: kd> !thread 89af7030 
THREAD 89af7030  Cid 0004.11e4  Teb: 00000000 Win32Thread: 00000000 WAIT: (Executive) KernelMode Non-Alertable
    820fae94  NotificationEvent
    820fae84  NotificationEvent
    820fae0c  NotificationEvent
    820faeb8  NotificationEvent
Not impersonating
DeviceMap                 83207d08
Owning Process            0       Image:         <Unknown>
Attached Process          86b97720       Image:         System
Wait Start TickCount      107512         Ticks: 5 (0:00:00:00.078)
Context Switch Count      23402            
UserTime                  00:00:00.000
KernelTime                00:00:03.463
Win32 Start Address nt!PfTLoggingWorker (0x821fffaf)
Stack Init 9d085000 Current 9d084c28 Base 9d085000 Limit 9d082000 Call 0
Priority 13 BasePriority 7 PriorityDecrement 6 IoPriority 2 PagePriority 5

 

'Programming' 카테고리의 다른 글

Example I/O request - an overview  (0) 2009.04.21
On-demand 메모리 관리  (0) 2009.04.02
Windbg Stack Backtracing 명령어  (0) 2009.03.27
Intel CPU registers  (0) 2009.03.20
Windbg Remote debugging 설정 방법  (0) 2009.03.20
Posted by noenemy
,

thread별로 로컬 변수나 함수 호출간에 전달할 파라미터 정보를 저장하기 위한 임시 공간으로서 thread stack을 사용할 수 있는데, thread의 특정 시점에 사용 중이던 stack 정보를 역으로 추적해서 현재 실행 중인 함수의 위치까지 실행된 과정을 call stack으로 보여주고, 각 함수에 전달된 파라미터 정보를 확인하는 과정을 Stack backtracing이라고 합니다. 다음에 기회가 되면 이와 관련된 함수 호출 규약(function calling convention) stack 사용 및 해제하는 과정을 다루도록 하겠습니다.

 

어느 debugger를 이용하든지 thread stack backtracing 을 해서 stack frame 정보를 확인하는 것이 live debugging이나 post mortem debugging에 필수 과정이라고 할 수 있습니다. 특히 windbg의 경우 stack backtracing을 위해 k 명령어를 제공하고 있는데 파라미터에 따라서 그 사용법이 매우 다양하기 때문에 어떤 것을 사용해야 되는지 헷갈리는 경우가 많습니다. 제 경우에도 주로 사용하는 몇 개의 명령어만 쓰고 있는데 이번 기회에 세부 사용법을 정리해보도록 하겠습니다. 일단 이것 저것 많이 써보면서 몸으로 익히는 게 중요할 것 같습니다.

 

세부 내용은 WinDbg의 매뉴얼을 참고 했습니다.

 

구문

*유저모드에서

[~Thread] k[b|p|P|v] [n] [f] [L] [FrameCount]
[~Thread] k[b|p|P|v] [n] [f] [L] = BasePtr [FrameCount]
[~Thread] k[b|p|P|v] [n] [f] [L] = BasePtr StackPtr InstructionPtr 
[~Thread] kd [WordCount]

*커널모드에서

[Processor] k[b|p|P|v] [n] [f] [L] [FrameCount]
[Processor] k[b|p|P|v] [n] [f] [L] = BasePtr [FrameCount]
[Processor] k[b|p|P|v] [n] [f] [L] = BasePtr StackPtr InstructionPtr 
[Processor] kd [WordCount]

파라미터

 

b: 각 함수에 전달된 파라미터를 3개씩 보기

p: 함수에 전달된 모든 파라미터 보기

P: 함수에 전달된 모든 파라미터 보기. 줄바꿈을 이용해서 보여준다.

v: FPO(Frame Pointer Omission) 정보 보기

n: frame number 보기

f: frame 사이의 간격(실제 스택상에서 해당 frame bytes ) 보기

L: 소스 상에서의 라인 번호 숨기기

 

실제 예

동일한 thread에서 k 명령어의 사용에 따른 차이점을 아래 예를 통해서 확인할 수 있습니다.

 

1: kd> k

ChildEBP RetAddr 

83093868 8208fbf4 nt!MmAccessFault+0x106 [d:\vista_ldr\base\ntos\mm\mmfault.c @ 251]

83093868 82091f60 nt!_KiTrap0E+0xdc [d:\vista_ldr\base\ntos\ke\i386\trap.asm @ 5651]

830938f0 8fc9dbbb nt!Exfi386InterlockedExchangeUlong [d:\vista_ldr\base\ntos\ex\i386\intrlfst.asm @ 782]

83093904 8204b2e7 C7xUSBV3!powerWaitWakeCallback+0x1b [c:\projects\wibro\usb\xp\miniport.08.06.24_328\power.c @ 399]

8309392c 822cec69 nt!PopRequestCompletion+0x38 [d:\vista_ldr\base\ntos\po\pocall.c @ 349]

83093964 820acc1b nt!IovpLocalCompletionRoutine+0xcc [d:\vista_ldr\base\ntos\io\iomgr\ioverifier.c @ 1028]

8309399c 822ceb53 nt!IopfCompleteRequest+0x11d [d:\vista_ldr\base\ntos\io\iomgr\iosubs.c @ 3848]

83093a0c 8f7431f4 nt!IovCompleteRequest+0x11c [d:\vista_ldr\base\ntos\io\iomgr\ioverifier.c @ 946]

83093a20 8f74a7f6 usbhub!UsbhCompletePdoWakeIrp+0xaf [d:\vistartm\drivers\wdm\usb\hub\usbhub\pdopwr.c @ 1864]

83093a40 8f74a9e0 usbhub!UsbhPdoRemoveCleanup+0x3f [d:\vistartm\drivers\wdm\usb\hub\usbhub\pdo.c @ 1267]

83093a58 8f72e41e usbhub!UsbhPdoPnp_RemoveDevice+0x41 [d:\vistartm\drivers\wdm\usb\hub\usbhub\pdo.c @ 2152]

83093a74 8f726c92 usbhub!UsbhPdoPnp+0x78 [d:\vistartm\drivers\wdm\usb\hub\usbhub\pnp.c @ 1759]

83093a88 822ce681 usbhub!UsbhGenDispatch+0x4a [d:\vistartm\drivers\wdm\usb\hub\usbhub\hub.c @ 1116]

83093aac 82027f1c nt!IovCallDriver+0x252 [d:\vista_ldr\base\ntos\io\iomgr\ioverifier.c @ 574]

83093ac0 825cfce9 nt!IofCallDriver+0x1b [d:\vista_ldr\base\ntos\io\iomgr\iosubs.c @ 2370]

83093b08 822ce681 ndis!ndisPnPDispatch+0x4a4 [d:\vistartm\net\ndis\sys\ndispnp.c @ 1426]

83093b2c 82027f1c nt!IovCallDriver+0x252 [d:\vista_ldr\base\ntos\io\iomgr\ioverifier.c @ 574]

83093b40 821af73b nt!IofCallDriver+0x1b [d:\vista_ldr\base\ntos\io\iomgr\iosubs.c @ 2370]

83093b74 821af9a3 nt!IopSynchronousCall+0xce [d:\vista_ldr\base\ntos\io\pnpmgr\irp.c @ 215]

83093bd0 82006592 nt!IopRemoveDevice+0xd5 [d:\vista_ldr\base\ntos\io\pnpmgr\irp.c @ 663]

 

1: kd> kd 5

83093868  83093880

8309386c  8208fbf4 nt!_KiTrap0E+0xdc [d:\vista_ldr\base\ntos\ke\i386\trap.asm @ 5651]

83093870  00000001

83093874  9112ee50

83093878  00000000

 

1: kd> kbL

ChildEBP RetAddr  Args to Child             

83093868 8208fbf4 00000001 9112ee50 00000000 nt!MmAccessFault+0x106

83093868 82091f60 00000001 9112ee50 00000000 nt!_KiTrap0E+0xdc

830938f0 8fc9dbbb a78aae90 898b30b0 a78aaf00 nt!Exfi386InterlockedExchangeUlong

83093904 8204b2e7 89683700 898b3000 00000004 C7xUSBV3!powerWaitWakeCallback+0x1b

8309392c 822cec69 00000000 a78aae90 898b3000 nt!PopRequestCompletion+0x38

83093964 820acc1b 00000000 a78aae90 830939d4 nt!IovpLocalCompletionRoutine+0xcc

8309399c 822ceb53 a78aae90 896837b8 c0000120 nt!IopfCompleteRequest+0x11d

83093a0c 8f7431f4 c0000120 896837b8 89683700 nt!IovCompleteRequest+0x11c

83093a20 8f74a7f6 89522028 89683700 c0000120 usbhub!UsbhCompletePdoWakeIrp+0xaf

83093a40 8f74a9e0 89683700 a7834eb8 a7834fdc usbhub!UsbhPdoRemoveCleanup+0x3f

83093a58 8f72e41e 89683700 a7834eb8 a7834eb8 usbhub!UsbhPdoPnp_RemoveDevice+0x41

83093a74 8f726c92 89683700 a7834eb8 89683700 usbhub!UsbhPdoPnp+0x78

83093a88 822ce681 89683700 a7834eb8 a7834eb8 usbhub!UsbhGenDispatch+0x4a

83093aac 82027f1c 825cfce9 00000000 89683700 nt!IovCallDriver+0x252

83093ac0 825cfce9 a7834eb8 892f6030 875fce30 nt!IofCallDriver+0x1b

83093b08 822ce681 892f6030 00000002 a7835000 ndis!ndisPnPDispatch+0x4a4

83093b2c 82027f1c 821af73b 83093bcc 892f6030 nt!IovCallDriver+0x252

83093b40 821af73b 89683700 89301ea8 89683700 nt!IofCallDriver+0x1b

83093b74 821af9a3 89683700 83093ba8 00000000 nt!IopSynchronousCall+0xce

83093bd0 82006592 89683700 00000002 9f7d2510 nt!IopRemoveDevice+0xd5

 

1: kd> kvL

ChildEBP RetAddr  Args to Child             

83093868 8208fbf4 00000001 9112ee50 00000000 nt!MmAccessFault+0x106 (CONV: stdcall)

83093868 82091f60 00000001 9112ee50 00000000 nt!_KiTrap0E+0xdc (FPO: [0,0] TrapFrame @ 83093880) (CONV: cdecl)

830938f0 8fc9dbbb a78aae90 898b30b0 a78aaf00 nt!Exfi386InterlockedExchangeUlong (FPO: [0,0,0])

83093904 8204b2e7 89683700 898b3000 00000004 C7xUSBV3!powerWaitWakeCallback+0x1b (FPO: [Non-Fpo]) (CONV: stdcall)

8309392c 822cec69 00000000 a78aae90 898b3000 nt!PopRequestCompletion+0x38 (CONV: stdcall)

83093964 820acc1b 00000000 a78aae90 830939d4 nt!IovpLocalCompletionRoutine+0xcc (CONV: stdcall)

8309399c 822ceb53 a78aae90 896837b8 c0000120 nt!IopfCompleteRequest+0x11d (CONV: fastcall)

83093a0c 8f7431f4 c0000120 896837b8 89683700 nt!IovCompleteRequest+0x11c (CONV: fastcall)

83093a20 8f74a7f6 89522028 89683700 c0000120 usbhub!UsbhCompletePdoWakeIrp+0xaf (FPO: [Non-Fpo]) (CONV: stdcall)

83093a40 8f74a9e0 89683700 a7834eb8 a7834fdc usbhub!UsbhPdoRemoveCleanup+0x3f (FPO: [Non-Fpo]) (CONV: stdcall)

83093a58 8f72e41e 89683700 a7834eb8 a7834eb8 usbhub!UsbhPdoPnp_RemoveDevice+0x41 (FPO: [Non-Fpo]) (CONV: stdcall)

83093a74 8f726c92 89683700 a7834eb8 89683700 usbhub!UsbhPdoPnp+0x78 (FPO: [Non-Fpo]) (CONV: stdcall)

83093a88 822ce681 89683700 a7834eb8 a7834eb8 usbhub!UsbhGenDispatch+0x4a (FPO: [Non-Fpo]) (CONV: stdcall)

83093aac 82027f1c 825cfce9 00000000 89683700 nt!IovCallDriver+0x252 (CONV: fastcall)

83093ac0 825cfce9 a7834eb8 892f6030 875fce30 nt!IofCallDriver+0x1b (CONV: fastcall)

83093b08 822ce681 892f6030 00000002 a7835000 ndis!ndisPnPDispatch+0x4a4 (FPO: [Non-Fpo]) (CONV: stdcall)

83093b2c 82027f1c 821af73b 83093bcc 892f6030 nt!IovCallDriver+0x252 (CONV: fastcall)

83093b40 821af73b 89683700 89301ea8 89683700 nt!IofCallDriver+0x1b (CONV: fastcall)

83093b74 821af9a3 89683700 83093ba8 00000000 nt!IopSynchronousCall+0xce (CONV: stdcall)

83093bd0 82006592 89683700 00000002 9f7d2510 nt!IopRemoveDevice+0xd5 (CONV: stdcall)

 

1: kd> kpL

ChildEBP RetAddr 

83093868 8208fbf4 nt!MmAccessFault(unsigned long FaultStatus = 1, void * VirtualAddress = 0x9112ee50, char PreviousMode = 0 '', void * TrapInformation = 0x83093880)+0x106

83093868 82091f60 nt!_KiTrap0E(void)+0xdc

830938f0 8fc9dbbb nt!Exfi386InterlockedExchangeUlong(void)

83093904 8204b2e7 C7xUSBV3!powerWaitWakeCallback(struct _DEVICE_OBJECT * Object = 0x89683700, unsigned char MinorFunction = 0x00 '', union _POWER_STATE PowerState = union _POWER_STATE, struct _MINIPORT_ADAPTER * Adapter = 0x9112eb50, struct _IO_STATUS_BLOCK * IoStatus = 0xa78aaea8)+0x1b

8309392c 822cec69 nt!PopRequestCompletion(struct _DEVICE_OBJECT * DeviceObject = 0x00000000, struct _IRP * Irp = 0xa78aae90, void * Context = 0x898b3000)+0x38

83093964 820acc1b nt!IovpLocalCompletionRoutine(struct _DEVICE_OBJECT * DeviceObject = 0x00000000, struct _IRP * Irp = 0xa78aae90, void * Context = 0x830939d4)+0xcc

8309399c 822ceb53 nt!IopfCompleteRequest(struct _IRP * Irp = 0x9112ee50, char PriorityBoost = 0 '')+0x11d

83093a0c 8f7431f4 nt!IovCompleteRequest(struct _IRP * Irp = 0x9112ee50, char PriorityBoost = 0 '')+0x11c

83093a20 8f74a7f6 usbhub!UsbhCompletePdoWakeIrp(struct _DEVICE_OBJECT * HubFdo = 0x89522028, struct _DEVICE_OBJECT * Pdo = 0x89683700, long NtStatus = -1073741536)+0xaf

83093a40 8f74a9e0 usbhub!UsbhPdoRemoveCleanup(struct _DEVICE_OBJECT * Pdo = 0x89683700)+0x3f

83093a58 8f72e41e usbhub!UsbhPdoPnp_RemoveDevice(struct _DEVICE_OBJECT * Pdo = 0x89683700, struct _IRP * Irp = 0xa7834eb8)+0x41

83093a74 8f726c92 usbhub!UsbhPdoPnp(struct _DEVICE_OBJECT * HubPdo = 0x89683700, struct _IRP * Irp = 0xa7834eb8)+0x78

83093a88 822ce681 usbhub!UsbhGenDispatch(struct _DEVICE_OBJECT * DeviceObject = 0x89683700, struct _IRP * Irp = 0xa7834eb8)+0x4a

83093aac 82027f1c nt!IovCallDriver(struct _DEVICE_OBJECT * DeviceObject = 0x9112ee50, struct _IRP * Irp = 0x00000000, void * ReturnAddress = 0x825cfce9)+0x252

83093ac0 825cfce9 nt!IofCallDriver(struct _DEVICE_OBJECT * DeviceObject = 0x9112ee50, struct _IRP * Irp = 0x00000000)+0x1b

83093b08 822ce681 ndis!ndisPnPDispatch(struct _DEVICE_OBJECT * DeviceObject = 0x892f6030, struct _IRP * Irp = 0x00000002)+0x4a4

83093b2c 82027f1c nt!IovCallDriver(struct _DEVICE_OBJECT * DeviceObject = 0x9112ee50, struct _IRP * Irp = 0x00000000, void * ReturnAddress = 0x821af73b)+0x252

83093b40 821af73b nt!IofCallDriver(struct _DEVICE_OBJECT * DeviceObject = 0x9112ee50, struct _IRP * Irp = 0x00000000)+0x1b

83093b74 821af9a3 nt!IopSynchronousCall(struct _DEVICE_OBJECT * DeviceObject = 0x89683700, struct _IO_STACK_LOCATION * TopStackLocation = 0x83093ba8, long DefaultStatus = -1882596448, unsigned long DefaultInformation = 0x83093bd0, unsigned long * Information = 0x00000000)+0xce

83093bd0 82006592 nt!IopRemoveDevice(struct _DEVICE_OBJECT * TargetDevice = 0x89683700, unsigned long IrpMinorCode = 2)+0xd5

 

1: kd> kPL

ChildEBP RetAddr 

83093868 8208fbf4 nt!MmAccessFault(

                                unsigned long FaultStatus = 1,

                                void * VirtualAddress = 0x9112ee50,

                                char PreviousMode = 0 '',

                                void * TrapInformation = 0x83093880)+0x106

83093868 82091f60 nt!_KiTrap0E(void)+0xdc

830938f0 8fc9dbbb nt!Exfi386InterlockedExchangeUlong(void)

83093904 8204b2e7 C7xUSBV3!powerWaitWakeCallback(

                                struct _DEVICE_OBJECT * Object = 0x89683700,

                                unsigned char MinorFunction = 0x00 '',

                                union _POWER_STATE PowerState = union _POWER_STATE,

                                struct _MINIPORT_ADAPTER * Adapter = 0x9112eb50,

                                struct _IO_STATUS_BLOCK * IoStatus = 0xa78aaea8)+0x1b

8309392c 822cec69 nt!PopRequestCompletion(

                                struct _DEVICE_OBJECT * DeviceObject = 0x00000000,

                                struct _IRP * Irp = 0xa78aae90,

                                void * Context = 0x898b3000)+0x38

83093964 820acc1b nt!IovpLocalCompletionRoutine(

                                struct _DEVICE_OBJECT * DeviceObject = 0x00000000,

                                struct _IRP * Irp = 0xa78aae90,

                                void * Context = 0x830939d4)+0xcc

8309399c 822ceb53 nt!IopfCompleteRequest(

                                struct _IRP * Irp = 0x9112ee50,

                                char PriorityBoost = 0 '')+0x11d

83093a0c 8f7431f4 nt!IovCompleteRequest(

                                struct _IRP * Irp = 0x9112ee50,

                                char PriorityBoost = 0 '')+0x11c

83093a20 8f74a7f6 usbhub!UsbhCompletePdoWakeIrp(

                                struct _DEVICE_OBJECT * HubFdo = 0x89522028,

                                struct _DEVICE_OBJECT * Pdo = 0x89683700,

                                long NtStatus = -1073741536)+0xaf

83093a40 8f74a9e0 usbhub!UsbhPdoRemoveCleanup(

                                struct _DEVICE_OBJECT * Pdo = 0x89683700)+0x3f

83093a58 8f72e41e usbhub!UsbhPdoPnp_RemoveDevice(

                                struct _DEVICE_OBJECT * Pdo = 0x89683700,

                                struct _IRP * Irp = 0xa7834eb8)+0x41

83093a74 8f726c92 usbhub!UsbhPdoPnp(

                                struct _DEVICE_OBJECT * HubPdo = 0x89683700,

                                struct _IRP * Irp = 0xa7834eb8)+0x78

83093a88 822ce681 usbhub!UsbhGenDispatch(

                                struct _DEVICE_OBJECT * DeviceObject = 0x89683700,

                                struct _IRP * Irp = 0xa7834eb8)+0x4a

83093aac 82027f1c nt!IovCallDriver(

                                struct _DEVICE_OBJECT * DeviceObject = 0x9112ee50,

                                struct _IRP * Irp = 0x00000000,

                                void * ReturnAddress = 0x825cfce9)+0x252

83093ac0 825cfce9 nt!IofCallDriver(

                                struct _DEVICE_OBJECT * DeviceObject = 0x9112ee50,

                                struct _IRP * Irp = 0x00000000)+0x1b

83093b08 822ce681 ndis!ndisPnPDispatch(

                                struct _DEVICE_OBJECT * DeviceObject = 0x892f6030,

                                struct _IRP * Irp = 0x00000002)+0x4a4

83093b2c 82027f1c nt!IovCallDriver(

                                struct _DEVICE_OBJECT * DeviceObject = 0x9112ee50,

                                struct _IRP * Irp = 0x00000000,

                                void * ReturnAddress = 0x821af73b)+0x252

83093b40 821af73b nt!IofCallDriver(

                                struct _DEVICE_OBJECT * DeviceObject = 0x9112ee50,

                                struct _IRP * Irp = 0x00000000)+0x1b

83093b74 821af9a3 nt!IopSynchronousCall(

                                struct _DEVICE_OBJECT * DeviceObject = 0x89683700,

                                struct _IO_STACK_LOCATION * TopStackLocation = 0x83093ba8,

                                long DefaultStatus = -1882596448,

                                unsigned long DefaultInformation = 0x83093bd0,

                                unsigned long * Information = 0x00000000)+0xce

83093bd0 82006592 nt!IopRemoveDevice(

                                struct _DEVICE_OBJECT * TargetDevice = 0x89683700,

                                unsigned long IrpMinorCode = 2)+0xd5

 

1: kd> kfL

  Memory  ChildEBP RetAddr 

          83093868 8208fbf4 nt!MmAccessFault+0x106

        0 83093868 82091f60 nt!_KiTrap0E+0xdc

       88 830938f0 8fc9dbbb nt!Exfi386InterlockedExchangeUlong

       14 83093904 8204b2e7 C7xUSBV3!powerWaitWakeCallback+0x1b

       28 8309392c 822cec69 nt!PopRequestCompletion+0x38

       38 83093964 820acc1b nt!IovpLocalCompletionRoutine+0xcc

       38 8309399c 822ceb53 nt!IopfCompleteRequest+0x11d

       70 83093a0c 8f7431f4 nt!IovCompleteRequest+0x11c

       14 83093a20 8f74a7f6 usbhub!UsbhCompletePdoWakeIrp+0xaf

       20 83093a40 8f74a9e0 usbhub!UsbhPdoRemoveCleanup+0x3f

       18 83093a58 8f72e41e usbhub!UsbhPdoPnp_RemoveDevice+0x41

       1c 83093a74 8f726c92 usbhub!UsbhPdoPnp+0x78

       14 83093a88 822ce681 usbhub!UsbhGenDispatch+0x4a

       24 83093aac 82027f1c nt!IovCallDriver+0x252

       14 83093ac0 825cfce9 nt!IofCallDriver+0x1b

       48 83093b08 822ce681 ndis!ndisPnPDispatch+0x4a4

       24 83093b2c 82027f1c nt!IovCallDriver+0x252

       14 83093b40 821af73b nt!IofCallDriver+0x1b

       34 83093b74 821af9a3 nt!IopSynchronousCall+0xce

       5c 83093bd0 82006592 nt!IopRemoveDevice+0xd5

'Programming' 카테고리의 다른 글

On-demand 메모리 관리  (0) 2009.04.02
Thread States  (0) 2009.03.27
Intel CPU registers  (0) 2009.03.20
Windbg Remote debugging 설정 방법  (0) 2009.03.20
Windows Error Reporting(WER)이란  (0) 2009.02.25
Posted by noenemy
,

Intel CPU registers

Programming 2009. 3. 20. 20:10
CPU에서 어떤 명령이 실행되기 위해서는 메모리에 있는 내용이 CPU로 전달되어야 하는데, CPU와 메모리 사이에 데이터가 매번 전송되는 것이 성능상에 문제가 될 수 있기 때문에 CPU 내에 여러 개의 임시 저장소를 가지고 있는데 이를 레지스터(Register)라고 합니다. CPU가 발전함에 따라 레지스터의 크기가 변하기도 하고, 새로운 기능이 추가되면서 레지스터가 추가되기도 합니다. 여기서는 Intel 80386 CPU를 기준으로 가장 일반적으로 사용되는 레지스터들을 나열해 보았습니다.

 

각 레지스터에 대한 보다 자세한 내용은 Intel CPU manual(http://www.intel.com/products/processor/manuals/)을 참고하시기 바랍니다.

 

일반목적의 레지스터

l  EAX : Accumulator (함수의 return value로 사용)

l  EBX : Points to data in DS

l  ECX : Counting

l  EDX : I/O pointer

l  ESI : Source ptr for strings

l  EDI : Destination ptr fro strings

 

특수한 목적의 레지스터

l  ESP : Stack pointer (현재 thread stacktop 위치를 가리키는 pointer)

l  EBP : Points to data on stack (stack frame을 구성하는데 사용)

l  EIP : Instruction pointer(다음에 CPU에서 실행되어야 할 instruction을 가리킴)

 

EFLAGS 레지스터

l  Status Flags

n  CF : Carry Flag

n  PF : Parity Flags

n  AF : Auxiliary Carry Flag

n  ZF : Zero Flag

n  SF : Sign Flag

n  OF : Overflow Flag

l  Control Flag

n  DF : direction Flag

l  System Flags

n  IF : Interrupt Enable Flag

n  TF : Trap Flag

n  IOPL : I/O Privilege Level

n  NT : Nested Task Flag

n  RF : Resume Flag

n  VM : Virtual 8086 mode

n  AC : Alignment Check (486 only)

 

Segment 레지스터

l  CS : Code segment

l  DS : Data segment

l  SS : Stack segment

l  ES : Extra data segment

l  FS : Extra data segment introduced with 386

l  GS : Extra data segmet introduced with 386

'Programming' 카테고리의 다른 글

Thread States  (0) 2009.03.27
Windbg Stack Backtracing 명령어  (0) 2009.03.27
Windbg Remote debugging 설정 방법  (0) 2009.03.20
Windows Error Reporting(WER)이란  (0) 2009.02.25
강제로 덤프파일 수집하기  (0) 2009.02.19
Posted by noenemy
,

오늘은 WinDbg를 이용해서 remote debugging을 하는 방법을 알아보려 합니다.

 

원격지의 WinDbg 프로그램을 서로 Server, Client 처럼 TCP/IP나 named pipe를 이용해서 통신하게 함으로써 debugging을 하는 방법입니다. 이 방법은 실제 debugging을 진행할 사람과 재현 장비가 멀리 떨어져 있는 경우 네트웤을 통해 디버깅을 할 수 있게 해주므로 매우 유용하게 사용할 수 있습니다. 다만 이렇게 WinDbg 끼리 서로 통신하려면 상호간에 연결이 되어야 하므로 약간을 설정이 필요합니다.

 

여기서는 TCP/IP를 이용한 remote debugging 방법을 알아보도록 하지요.

 

다음과 같은 상황을 가정해 보았습니다.

 

 

우선 일반적으로 kernel debugging을 하기 위한 환경 설정을 먼저 진행합니다. Target machine과 Host machine을 1394를 이용해서 연결하는 과정입니다.
(
세부 내용은 http://msdn.microsoft.com/en-us/library/cc266332.aspx 참고)

 

1.     일반적으로 kernel debugging을 위해서 target machine host machine 1394 cable을 이용해서 연결한 뒤

2.     Target machine debug mode로 부팅하고 (boot.ini 수정이나 vista에서는 bcdedit.exe 설정 필요)

3.     Host machine에서는 WinDbg를 실행시킨 후 kernel debug를 시작한다.

4.     Target machine Host machine windbg가 연결되면 kernel debugging이 가능하다.

 

자..여기까지 진행되었다면 Host machine과 원격지에 있는 Remote machine을 연결하는 방법을 알아보도록 하겠습니다.
현재 상황에서는 Host machine의 WinDbg가 server의 역할을, 그리고 Remote machine의 WinDbg가 client의 역할을 하게 됩니다.

즉, Hostmachine WinDbg Remote machine WinDbg가 서로 연결되어 통신할 수 있다면, Remote machine에서 Host machine을 거쳐서 Target machine kernel debugging을 하는 것이 가능해집니다.

 

Host machine Remote machine TCP/IP named pipe로 연결이 가능한데, 여기서는 TCP/IP를 이용한 네트워크 연결법을 알아보도록 하겠습니다. 

 

5.     Host machine에서 windbg break한 상태에서 kernel debug mode에서 다음과 같이 입력합니다.

A.     Kd> .server tcp:Port=<port number>

B.      Host machine windbg에서 server start 되었다는 메시지가 보여집니다. , Host machine에서 지정한 port number remote machine이 연결하기를 기다리는 상태가 됩니다.

 

이제 원격지에서 실제로 debugging할 엔지니어에게 host machine에 접근할 수 있는 장비명(or IP 주소) Port 번호를 알려줍니다. 만약 중간에 방화벽 같은 게 있다면 접근이 허용될 수 있도록 설정을 해줘야 합니다.

 

이제 Remote machine에서 Host machine으로 접근해 보겠습니다.

 

6.     Remote machine WinDbg file 메뉴에서 ‘connect to remote session’을 선택하고 접근할 Host machine의 server name(or IP 주소)과 지정한 port 번호를 입력합니다.

 

 

          

 

7.     연결에 성공하였다면 Remote machine WinDbg에서 다음과 같은 메시지를 볼 수 있습니다.

 

Microsoft (R) Windows Debugger Version 6.11.0001.402 X86

Copyright (c) Microsoft Corporation. All rights reserved.

 

Server started.  Client can connect with any of these command lines

0: <debugger> -remote tcp:Port=10123,Server=SOONKKIM2

SOONKKIM1\soonkkim (tcp 157.60.9.124:43460) connected at Fri Mar 20 15:52:52 2009

 

8.     Remote machine WinDbg를 이용해서 debugging을 진행하면 됩니다.

 

'Programming' 카테고리의 다른 글

Windbg Stack Backtracing 명령어  (0) 2009.03.27
Intel CPU registers  (0) 2009.03.20
Windows Error Reporting(WER)이란  (0) 2009.02.25
강제로 덤프파일 수집하기  (0) 2009.02.19
Driver Verifier에 대해서  (0) 2009.02.09
Posted by noenemy
,

오늘은 흔히 WER이라고 불리우는 Windows Error Reporting에 대해서 알아보도록 하겠습니다.

Windows XP 이후로 시스템이 비정상 종료된 이후에 다시 부팅을 하면 '오류로 부터 복구 되었는데 이를 보고하겠느냐'라는 메시지 박스가 뜨는 것을 볼 수 있습니다. 이 기능을 이용해서 사용자들로부터 수집된 오류 데이터를 이용해서 어떠한 문제로 사용자들이 불편을 겪고 있는지, 그 문제가 어떤 모듈에서 발생을 한 것인지 확인하고 발생 빈도가 높은 문제는 긴급한 이슈로 인식하고 문제를 수정하고 hotfix가 제작될 수 있도록 할 수 있습니다. 이러한 과정을 통해서 실제 사용자에게 발생하는 오류들을 수집하고 모니터링함으로써 보다 안정적인 환경에서 컴퓨터를 사용할 수 있도록 하고자 하는 것이 WER 서비스의 목적이라고 할 수 있습니다.

              [그림] WER 데이터의 수집 및 해결 과정

이 서비스를 잘 이용하면 마이크로소프트 뿐만 아니라 커널 모드에서 문제를 발생시킬 수 있는 소프트웨어를 개발하는 업체(ISV : Indenpendt Software Vendor)나 하드웨어 개발 업체(IHV - Indenpendent Hardware Vendor), 제조업체(OEM : Original hardware Manufacturer)에게 자사의 제품을 보다 안정성을 높이는데 매우 유용하게 사용될 수 있습니다. 왜냐하면 이들 업체에서는 대부분 제품을 실제 시장에 내보내기 전에 내부적으로 여러 가지 상황을 대비해서 테스트를 진행하고 품질을 검증한 뒤에 출시를 하게 되는데, 실제 사용자들이 사용하는 모든 다양한 환경에서 테스트를 진행하지 못하기 때문에 예상못한 상황에 대해서 사용자들이 겪고 있는 문제점들을 수집할 수 있는 매우 좋은 기회가 됩니다.

WER을 이용해서 전세계의 사용자에 의해서 매우 방대한 분량의 오류가 보고되고 있는데, 마이크로소프트에서는 이를 bucket 이란 가상의 단위로 관리합니다. 즉 수집된 오류 중에서 특정 버전의 드라이버나 애플리케이션이나 윈도우 기능이나 구성요소와 관련된 오류를 분류하여 동일하다고 판단되는 내용을 하나의 bucket으로 관리합니다. 따라서 bucket에 대한 시간에 따른 발생 빈도수나 발생 추이를 보면 해당 문제가 현재 얼마나 빈번하게 발생하는지, 또 그 오류가 확산되고 있는지 줄어들고 있는지에 대한 추적이 가능하게 됩니다.

WER에서 어떠한 정보들이 수집되는지?

다음과 같은 정보들이 수집됩니다.

  • 어떠한 소프트웨어나 하드웨어에서 문제가 발생했는지
  • 문제의 심각성 정도
  • 문제에 대하여 정의하는데 도움되는 파일들 - 시스템 파일이나 문제가 발생한 전이나 후의 소프트웨어 동작에 대한 리포트 파일들..
  • 기본적인 소프트웨어, 하드웨어 정보들 - 운영체제 버전, 언어, 장치 모델, 제조업체, 메모리나 디스크 크기 등

사용자의 장비에서 정보를 수집한다는 것은 개인 정보 보호 차원에서 매우 민감한 부분일 수 있습니다. WER의 개인 정보 보호 정책에 대한 내용은 아래 문서에서 확인할 수 있습니다.

Privacy Statement for the Microsoft Error Reporting Service
http://oca.microsoft.com/en/dcp20.asp


WER에서 수집된 오류 리포트를 보려면?

우선 다음과 같은 방법으로 마이크로소프트 Winqual(Windows Quality Online Services) 사이트에 등록하셔야 합니다.

1. Winqual 계정 만들기 : 다른 회사로 사칭하는 것을 막기 위해 VeriSign 인증서를 필요로 합니다.
2. WER 약관 동의하기
3. Winqual site에 로그인하기
4. Windows Error Reports 클릭


WER 사이트에 제품이나 파일 등록하기

앞서 설명드린 것처럼 수많은 오류 데이터가 수집되는데 특정 모듈이 어느 회사에서 작성한 제품이나 파일인지에 대한 정보를 알 수 있다면 보다 더 효율적으로 데이터를 이용할 수 있게 됩니다.  이를 위해서 여러분 회사에서 작성한 제품이나 파일에 대한 정보를 등록하면,  긴급하게 늘어나는 오류 상황이 발생했을 때 마이크로소프트와 여러분의 회사가 보다 신속하게 해당 문제를 해결하는데 도움이 됩니다.

1. Winqual 사이트의 Request file mapping이나 Request file unmapping 항목을 작성합니다.
2. 이 작업을 마친 후, 여러분의 회사와 관련된 파일들에 대한 정보를 확인할 수 있습니다.


추가적으로 다음 문서 내용을 참고하시면, WER 정보를 이용해서 개발자들이 실제 bucket 데이터를 어떻게 활용하고 대처할 수 있는지에 대한 정보를 얻을 수 있습니다.

Developers Guide to WER
https://winqual.microsoft.com/help/developers_guide_to_wer.htm


'Programming' 카테고리의 다른 글

Windbg Stack Backtracing 명령어  (0) 2009.03.27
Intel CPU registers  (0) 2009.03.20
Windbg Remote debugging 설정 방법  (0) 2009.03.20
강제로 덤프파일 수집하기  (0) 2009.02.19
Driver Verifier에 대해서  (0) 2009.02.09
Posted by noenemy
,

Kernel mode에서 처리할 수 없는 exception이 발생하는 경우 흔히 우리가 블루스크린이라고 말하는 BSOD(Blue Screen Of Death) 화면을 볼 수 있습니다. 이때 시스템에서 설정한 옵션에 따라 오류 발생 시점의 메모리 정보를 dump file에 저장함으로써 나중에 왜 블루스크린이 발생했는지에 대한 원인을 분석하는데 사용할 수 있습니다. 이러한 덤프 분석을 문제가 발생한 이후에 이를 조사한다는 의미에서 Post morterm analysis라는 용어를 쓰기도 합니다.

블루스크린이 발생하면 파란 배경화면에 발생한 오류에 대한 코드와 몇 가지 추가 정보가 파라미터로 보여지고 덤프 파일을 저장하는 과정이 보여집니다. 즉, 메모리 상태를 덤프해서 memory.dmp 파일(일반적으로 c:\Windows에 위치)에 저장을 하는 과정입니다. 일반 사용자에게는 컴퓨터를 사용 중에 갑자기 이 화면을 만나게 되면 작업이 중단되고 시스템이 재시작되어야 하므로 매우 곤욕스럽습니다. 하지만 원인을 분석하고 이를 해결함으로써 컴퓨터 사용환경이 보다 더 안정적으로 될 수 있는 기회가 되므로 엔지니어나 개발자에게는 이때 저장되는 덤프 파일 정보가 문제해결에 매우 중요한 단서가 됩니다.

명시적으로 오류가 발생해서 BSOD가 발생하고 덤프 파일이 수집이 가능한 경우가 대부분이지만, 특정 시점에 덤프 파일을 강제로 생성할 필요가 있는 경우도 있습니다. 예를 들어, 특정 시점에 컴퓨터의 반응이 불안정하거나 너무 느려진 경우(주로 hanging이라고 부름) 그 원인을 찾기 위해 덤프를 수집하고 이를 분석할 필요가 있는데, 이는 커널에서 특정 예외가 발생한 경우가 아니기 때문에 덤프가 생성이 되지를 않습니다. 그래서 강제로 특정 시점의 덤프를 수집할 필요가 있는데 다음과 같은 방법으로 수집이 가능합니다.

*키보드의 특수 키 조합으로 강제로 BSOD를 발생시키는 방법으로 사용중인 키보드에 따라서 이 방법을 사용하지 못할 수도 있습니다. 예를 들어 노트북의 경우 제조 모델에 따라 키패드의 조합이 다르고, 특히 오른쪽 Ctrl 키를 이용하므로 왼쪽 Ctrl 키만 있는 일부 키보드를 이용해서는 수집할 수 없습니다.

* How to get full dump file manually

1. 제어판 - 시스템 - 고급 - 시작 및 복구
2. 현재 서버의 물리적인 Memory 가 2GB 이하라면 “전체 메모리 덤프(Full Memory dump)” 로 설정합니다. 만약 2GB 이상이라면 “커널 메모리 덤프(Kernel Memory dump)” 로 설정하십시오.
3. 기존 파일에 덮어쓰기 : 옵션 선택 확인 (선택되어 있어야 합니다.)
4. %SystemRoot% 파티션에 Paging 파일이 존재해야 합니다.
5. Paging 파일(pagefile.sys)의 크기가 물리적인 메모리보다 최소한 같거나 커야 합니다.
6. 기본적으로 Memory Dump 는 C:\Windows 에 저장됩니다. C Drive 에 공간이 충분히 있는지 확인하십시오.
7. 레지스트리 편집기를 실행하여 아래 레지스트리 키를 추가한 후, 이를 적용하기 위하여 시스템을 재부팅 합니다.

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\i8042prt\Parameters
값 이름: CrashOnCtrlScroll
데이터 형식: REG_DWORD
값: 1

8. 오른쪽 Ctrl 키를 누른 상태에서 Scroll Lock 키를 두 번 누르면, BSOD가 발생하고 덤프가 수집됩니다.

*덤프 수집이 안된다면, 레지스트리 변경후 재부팅을 했는지 또는 오른쪽 Ctrl 키를 눌렀는지, Scroll Lock 키를 두 번 눌렀는지, 특수한 키보드를 사용중인지를 확인해보시기 바랍니다.

'Programming' 카테고리의 다른 글

Windbg Stack Backtracing 명령어  (0) 2009.03.27
Intel CPU registers  (0) 2009.03.20
Windbg Remote debugging 설정 방법  (0) 2009.03.20
Windows Error Reporting(WER)이란  (0) 2009.02.25
Driver Verifier에 대해서  (0) 2009.02.09
Posted by noenemy
,

Kernel 영역에서 exception이 발생하여 이에 대해서 handling되지 못하는 경우에는 흔히 우리가 블루스크린이라고 부르는 BSOD(Blue Screen Of Death) 화면이 보여지고 시스템 실행이 중단됩니다. 이는 운영체제 자체의 문제점에 의해 발생하는 경우도 있지만 대부분은 커널 영역에서 실행되는 3rd party driver에 의해서 발생하는 경우가 많습니다. 저희가 사용하는 시스템에는 운영체제가 설치된 이후로 수많은 응용 프로그램들이 추가로 설치되고 함께 실행되고 있고, 또한 운영체제 자체가 수많은 벤더에서 제작한 하드웨어의 조합으로 구성되어 있고 이에 따라 많은 3rd party device driver와 연동되어 실행됩니다. 이러한 이유에서 블루스크린이 발생했을 때에는 그 원인이 어디에 있는지 찾고 적절한 해결방법을 찾는 것이 중요합니다.

커널모드에서 실행되는 특정 드라이버가 시스템 불안정의 원인이라고 의심될 경우 이를 확인하기 위한 도구로서 Driver Verifier라는 유틸리티가 제공됩니다. 이는 Windows 2000 이후 버전부터 운영체제에 포함되어 함께 배포되고 있습니다. 간단히 명령창에서 verifier.exe를 실행시키면 다음과 같은 UI를 제공하는 프로그램이 실행됩니다. 또한 command 모드로도 실행이 가능한데 verifier /? 라고 실행하면 실행에 필요한 각종 옵션과 구문을 확인할 수 있습니다.

[그림] driver verfier의 실행 화면

Verifier 도구는 특히 device driver 개발자에게 유용하게 사용될 수 있는데 개발중인 driver 파일을 릴리즈하기 전에 작성한 모듈에 대해서 보다 엄격한 환경에서 테스트가 가능하므로 안정성을 높일 수 있습니다. 커널모드에서 BSOD가 발생한 경우에 수집된 memory dump 파일을 분석함으로써 문제의 원인을 찾을 수 있지만 memory dump 파일은 실제 exception이 발생한 시점의 메모리 상태에 대한 dump이므로, 실제로 문제의 원인이 되는 root cause를 밝히지는 못할 수 있습니다. 예를 들어, a.sys라는 드라이버에서 메모리를 corruption 시키고 b.sys에서 이 메모리에 접근함으로써 BSOD가 발생한 경우를 가정해보면 BSOD가 발생하고 dump가 수집된 상황은 b.sys에서 잘못된 메모리를 접근한 시점이 됩니다. 하지만 우리가 찾고자 하는 것은 이러한 memory를 corruption을 시킨 것이 a.sys라는 것을 찾아야 하는데 이럴 때 verifier를 이용해서 a.sys 드라이버에 대해서 감시함으로써 memory가 corruption 되는 시점에서 BSOD를 발생시키도록 할 수 있습니다.

Verifier에는 특정 driver가 가질 수 있는 여러 문제점들에 대해서 검증을 할 수 있도록 여러 옵션을 제공하고 있습니다. 실제 verifier를 사용하고 있는 분들도 이들 옵션이 의미하는 바에 대해서 모르는 경우가 많은데, 이들 옵션이 의미하는 것과 해당 옵션에서 잡을 수 있는 오류에 대해서 알고 있어야 원하는 결과를 얻을 수 있습니다. 무분별하게 verifier 옵션을 사용할 경우 오히려 찾으려는 문제점과 관련없는 쪽으로 시선을 돌리게 되어 시간을 헛되이 보낼 수도 있기 때문입니다.

이러한 의미에서 verifier가 제공하는 여러 옵션 항목과 그 역할을 알아보도록 하겠습니다.


[그림] verifier에서 제공하는 여러 검사 옵션들


1. Special pool

이 옵션이 활성화 되어 있으면, 검사 대상이 되는 driver에서 요청한 메모리에 대해서 일반적으로 사용되는 pool 영역이 아닌 special pool이라는 별도의 영역을 이용해서 할당합니다. 그리고 할당된 이후에 이 영역에 대한 메모리 사용시 모니터링함으로써 overrun, underrun, 이미 해제된 메모리에 접근하는 등의 잘못된 메모리 접근이 감지되면 바로 BSOD를 발생시킵니다.

2. Pool tracking

이 옵션이 활성화 되어 있으면, 특정 드라이버가 unload 되는 시점에  해당 드라이버에서 memory leak이 발생했는지 확인하고 있으면 BSOD를 발생시킵니다. 즉, 해당 드라이버에 의해서 할당된 메모리 영역에 대해서 해제가 되지 않은 채로 드라이버가 언로드가 되는 것을 감지하고 싶을 경우에 사용하면 됩니다.

3. Force IRQL checking

이 옵션이 활성화 되어 있으면 해당 드라이버가 적절한 IRQL에서 메모리에 접근하는지를 검사하게 됩니다. 커널 모드 드라이버는 page fault handler가 처리할 수 없는 high IRQL에서 메모리에 접근해서는 안됩니다. 왜냐하면 접근하려는 page가 page out되어 invalid한 상태일 경우 이를 다시 paging file에서 page in 시켜서 물리적 메모리로 불러와야 하는데 high IRQL에서는 이를 처리할 방법이 없기 때문입니다.

4. I/O verification

이 옵션이 활성화 되어 있으면, I/O manager가 해당 드라이버를 위한 IRPs를 special pool을 이용해서 할당하고 이를 모니터링합니다. 만약 올바르지 않은 상태에서 IRP가 completion 되거나 I/O manager에게 잘못된 device object가 전달되려고 하면 Bug check을 발생시킵니다.

5. Enhanced I/O verification

이 옵션이 활성화되면, 감시 대상이 되는 드라이버에 대한 모든 IRP를 모니터링하고 비동기 completion, device stack location을 제대로 관리하는지, device object를 한번만 제거하는지 등에 대한 검사를 수행합니다.

6. Deadlock detection (Win XP 이후)

이 옵션이 활성화되면, 해당 드라이버에서 spin lock, mutex, fast mutex을 사용하는 경우를 모니터링하고 잠재적으로 deadlock을 발생시킬 수 있는  코드가 있는지를 검증합니다.

7. DMA checking (Win XP 이후)

 DMA는 Direct Memory Access의 약자로서 CPU 도움없이 하드웨어가 물리적 메모리에 직접 접근할 수 있도록 해주는 기술을 말합니다. 이 옵션이 활성화 되어 있으면, DMA 관련 함수가 제대로 사용되는지 그리고 DMA 수행에 대해서 I/O manager가 제공하는 버퍼가 사용될 때 올바르게 사용되는지를 감시합니다.

8. Low resources simulation

일반적으로 커널모드 드라이버는 메모리 사용이 원활한 상태를 가정하고 개발이 되는데, 이 옵션을 활성화하면 시스템 자원이 부족하여 메모리 할당에 대한 요청을 제대로 처리할 수 없는 상황을 시뮬레이션합니다. 이러한 메모리 부족 상태에서 해당 드라이버가 적절하게 동작할 수 있는지 검증하는데 사용됩니다.

9. Disk Integrity Verification (Win 2003 이후)

 이 옵션이 활성화되면, 하드 디스크에 접근을 모니터링하고 디스크가 데이터를 제대로 보존하는지에 대해서 검증합니다.

10. IRP logging (Win 2003 이후)

이 옵션이 활성화되면, 해당 드라이버의 IRP 사용을 모니터링하고 이를 WMI 정보로 저장합니다. 이 WMI 정보를 텍스트 파일로 추출하려면 WDK에 포함되어 있는 DC2WMIParser.exe를 사용하면 됩니다.

[참고자료]

Windows 2000에서 Driver Verifier를 사용하여 장치 드라이버 문제를 해결하는 방법
http://support.microsoft.com/kb/244617

Driver Verifier
http://www.osronline.com/DDKx/ddtools/dv_7g8j.htm


'Programming' 카테고리의 다른 글

Windbg Stack Backtracing 명령어  (0) 2009.03.27
Intel CPU registers  (0) 2009.03.20
Windbg Remote debugging 설정 방법  (0) 2009.03.20
Windows Error Reporting(WER)이란  (0) 2009.02.25
강제로 덤프파일 수집하기  (0) 2009.02.19
Posted by noenemy
,

돌고 도는 세상

BlahBlah 2008. 12. 30. 18:00

경기 침체의 끝이 보이지 않는 가운데..
요즘 국회에서 벌어지고 있는 일들을 보면 참 답답하기만 합니다.

아무리 어두운 밤이 길다 한들 어김없이 아침에 해는 떠오르듯이..
다시 좋은 날 오겠지요?
아래 내용들을 보면 2009년을 앞두고 있는 지금의 저희 모습과 크게 다르지 않네요.
세상은 돌고 돌지 않습니까..

다만 여의도와 경복궁 근처에 계신 분들.. 제발 헛짓은 하지 말았음 좋겠습니다. 이제 그만~



중동특수가 끝나 갈 무렵 터진 율산부도사건으로 시중엔 돈이 돌지 않았다. 실물경기가 침체에 빠져 있었는데 업친데 덥친 격으로 ‘2차 오일쇼크마저 호되게 불어 닥쳤다. 원유값이 큰 폭으로 오르자 국가경제가 휘청거렸다. ‘아껴 쓰고 나눠 쓰고 바꿔 쓰고 다시 쓰는소비 절약 바람이 불었고 시간이 흐를수록 경기침체가 가속화되며 스태그플래이션(stagflation)이 또다시 발생하였다.

소득감소와 고용불안으로 투자심리가 위축되며 주택시장에도 한파가 몰아쳤다. 각종 건축자재 값이 올라 분양가격 인상이 불가피 했음에도 불구하고 아파트값이 오를 기미가 전혀 보이지 않았다. 실물경기가 호황일 때 발생한 1차 오일쇼크 때와는 달리 기존 아파트값은 여의도 지역을 제외하고 8.8 조치 이전보다 20-30% 가량 떨어졌다.

(79 7) 


불황의 골이 깊어지면서 두 손으로 꼽아야 할 정도로 여러 차례 주택경기 활성화대책을 마련하였으나 여전히 실마리를 찾지 못했다. 가수요 억제는 바람직했으나 현실적으로 실수요만으로 주택경기를 살리기가 벅찼던 것이다. 주택시장을 활발하게 움직이게 하기 위해서는 윤활유 역할을 하는 가수요가 어느 정도 필요했다.

-       1가구 2주택 면세기한을 1년에서 16개월로 연장

-       공공주택 전매금지 기간을 2년에서 6개월로 단축

-       신축주택을 매입할 경우 양도세 대폭 완화

투기 억제를 위한 제도적 안전장치를 하나 둘 제거했으나, 죽은 말에 채찍질 하듯 정책효과는 별로 없었다.

(82 6)



'BlahBlah' 카테고리의 다른 글

IPad를 카오디오로..  (1) 2010.04.06
Zune HD!  (0) 2009.12.09
서태지심포니 D-day  (6) 2008.09.27
입자가속기(LHC) 실험?  (5) 2008.09.12
4베이 세상..  (0) 2008.05.16
Posted by noenemy
,

Pleasantly Blue 공연(3/26)

Guitar 2008. 10. 22. 01:11

올해 초. 3월26일이었던가요..
기억이 가물가물하네요.
봄 햇살이 무척이나 따뜻했던 날로 기억합니다.

홍은동 힐튼호텔에서 있었던 회사 신제품 발표회에서 사내밴드의 공연이 있었습니다.
그때 공연 실황 모습을 잠깐 구경해 볼까요?

4 Non Blondes의  Pleasantly Blue라는 곡입니다.



다시 보니까 감회가 새롭습니다.
이때만 해도 제가 Boss의 SD-1 달랑 하나만 가지고 공연을 했던 때라..
솔로떄 부스팅이 되지 않아서 다른 소리에 묻혀서 잘 들리지 않습니다.

이 곡 악보가 없어서 그냥 듣고 카피한 관계로 솔로가 상당히 엉성합니다.
그래서 솔로가 잘 안들려서 천만다행이네요. :)

이 공연을 할 때가 아마도 아침 9시에서 10시 사이였을 겁니다.
세상에 아침9시에 공연이라니..




'Guitar' 카테고리의 다른 글

요즘 쓰는 이펙터  (0) 2008.09.11
지옥의 기타 트레이닝..  (0) 2008.04.03
3/20 Heroes 밴드 공연을 마치고..  (0) 2008.03.20
Heroes band rocks!!  (2) 2008.03.12
엠밴드 멤버모집 포스터  (6) 2007.12.07
Posted by noenemy
,

서태지심포니 D-day

BlahBlah 2008. 9. 27. 14:48


바로 오늘. 서태지 심포니 D-day입니다.
예매 사이트에서 수없이 새로 고침을 해서 겨우 무대 정면 좌석을 구했습니다.

서태지 공연 관람은 이번이 두 번째입니다. 지난 번 7집 발표이후 Zero 04 투어 때 3층 자리 겨우 구해서 공연을 봤었는데요.. 어렸을 때부터 너무 좋아하는 뮤지션이고, 나름 매니아라고 생각하고 있습니다만..

서태지 공연은 몇 년을 기다려야 가끔 볼 수 있는 데다가.. 추석 기차표보다 구하기 보다 더 힘든 예약 전쟁.. 조금 지치더군요. 그래도 Zero 04 투어 때 서태지 공연을 직접 봤다는 그 기억은 정말 좋은 추억으로 남아 있습니다.

하지만 이번 공연은 정말 반드시 가야겠다는 생각을 해봤습니다. 그야말로 rare item이라고 할 수 있죠. 메탈리카의 S&M 공연, U2의 심포니 공연 등을 함께 했던 거장 톨카 카쉬프와 로얄 필하모닉과 함께하는 클래시컬 조인트 공연을 볼 수 있는 기회니까요.

평생 다시는 보지 못할 공연일꺼라고 생각합니다. 준비기간이 많이 걸렸을 텐데, 딱 하루 1회 공연만 한다는게 너무 아쉬울 뿐이죠.


사용자 삽입 이미지


직장인인 저로서도 티켓 값은 선뜻 내기 힘들 정도로 비싸지만.. 멋진 공연을 보고 난 뒤의 그 느낌과 추억은 몇 년이 지나도 즐거움을 주더군요. 10만원으로 엠피쓰리 플레이어를 사면 수천 수만 곡을 언제든지 들을 수 있어서 좋겠지만.. 10만원으로 본 공연은 단 몇 시간이지만 그 감동은 몇 년이 지나도 잔잔한 감동으로 남는 거죠. 실질적인 만족감은 후자가 더 크다고 봅니다.

이제 몇 시간 남지 않았네요. 갑자기 날씨가 쌀쌀해 졌는데... 가을 저녁 상암 월드컵 경기장에서의 서태지 심포니 공연. 기대가 큽니다.




'BlahBlah' 카테고리의 다른 글

Zune HD!  (0) 2009.12.09
돌고 도는 세상  (0) 2008.12.30
입자가속기(LHC) 실험?  (5) 2008.09.12
4베이 세상..  (0) 2008.05.16
눈의 피로 풀기  (0) 2007.09.17
Posted by noenemy
,

작티 HD-1000 캠코더 구입해서 테스트 용으로 촬영한 동영상입니다.

Full HD로 촬영했으나, Movie Maker로 동영상 수정을 하기 위해
어쩔 수 없이 '바닥' 프로그램으로 WM8 인코딩을 했습니다.
이때까지만 해도 화질이 어느 정도 괜찮은 듯 했으나... Movie Maker로 편집후 다시 변환하니 화질이 많이 떨어지는군요.

어쨌거나 작티로 촬영하면 MP4 확장자를 가진 파일이 생성되는데..
이 파일 자체로 프리미어나 베가스 같은 프로그램에서 편집하는 방법을 아직 찾지를 못했습니다.
프로그램에서 MP4 파일을 인식을 못하는 군요..

촬영도 힘들지만.. 편집 기술을 익히려면 정말 많은 삽질을 해야 할 것 같습니다.

WM8 인코딩 결과물을 이용해서 Movie Maker로 편집한 결과


방에서 대충 통기타로 연주해 본 more than words..
전체 곡이 기억이 안나서 그냥 대충 띵띵 그려봤습니다. ㅎㅎ

'Diary' 카테고리의 다른 글

캠코더 Sanyo Xacti HD-1000  (0) 2008.09.23
Cambridge Audio DVD89 플레이어  (2) 2008.04.08
오래된 LP의 잡음 없애기..  (2) 2008.04.02
Denon 턴테이블 DP-300F  (3) 2008.03.31
LP의 세계로!!  (0) 2008.03.12
Posted by noenemy
,

최근에 회사에서 UCC 영상을 만들어 제출하는 행사가 있었는데..
팀으로 출전해서 예선을 겨우 턱걸이로 통과해서 본선에 진출하게 되었네요.

팀별로 본선 작품을 만드는데 $500의 예산을 지원 받게 되었는데..
이 금액으로 뭘 할까 하다가 요 녀석을 질렀습니다.
어차피 본선 작품 만들려면 캠코더가 필요 했거든요.

작티 씨리즈로 유명한 산요 VPC HD-1000이라는 모델입니다.

현재 출시되어 있는 Full HD 지원 모델 중에서는 가장 저렴하고 슬림한 모델이 아닌가 싶네요.

일단 제 개인용도가 아니라 동호회용으로 구입하는 지라..
이것 저것 많이 따져보지는 않았고 가볍고, 작고, 휴대하기 편한 녀석 중에서 성능이 좋은 것을 찾다 보니 딱 이 녀석이 적당하더군요.

사용자 삽입 이미지

아담한 사이즈에 간단한 조작법. 디자인도 깔끔.

사용자 삽입 이미지

당분간 재밌는 동영상 놀이를 할 수 있을 것 같습니다. 후훗!!

사용자 삽입 이미지

아직 매뉴얼도 다 읽어 보지 못한 생초보인데요..

테스트 삼아 이것 저것 찍어봤는데. 사진 찍는 것과  동영상 촬영은 전혀 다른 것이네요.
촬영해놓은 것들을 재생해보니 특히 인물 대상으로 촬영했을 때 무지하게 어중간한 구도가 계속 이어지네요.

드라마나 영화 촬영하시는 분들... 존경합니다. (__)

'Diary' 카테고리의 다른 글

작티 HD-1000 테스트 동영상  (4) 2008.09.24
Cambridge Audio DVD89 플레이어  (2) 2008.04.08
오래된 LP의 잡음 없애기..  (2) 2008.04.02
Denon 턴테이블 DP-300F  (3) 2008.03.31
LP의 세계로!!  (0) 2008.03.12
Posted by noenemy
,
가수 빅뱅이 아닌 실제 빅뱅을 만들어내는 실험이 갑자기 실시간 검색순위에 올랐더랬죠.
지구의 멸망을 불러올 것이라는 반대파와 물리학계의 일대 도약이 될 거라는 찬성파가 극심한 대립을 보이고 있는 가운데.. 도대체 무슨 얘기인지 알아들을 수 없어서 답답한 건 저 뿐만일까요? :)

캘리포니아 몬터레이에서 이 실험의 내용에 대해 설명해 준 컨퍼런스가 있었군요. 쉬운 예를 들어서 최대한 쉽게 설명한 것 같습니다만.. 여전히 뭐가 뭔지 잘 모르겠습니다.





힉스입자. 힉스필드라...
현대 물리학에서 설명할 수 없는 어떠한 값(H).. 공식이 정립되기 위해서 꼭 필요한 값인데 아직 정의되지 않은 그 값의 비밀을 풀어 줄 힉스(Higgs) 입자가 있을거라는 가설이 있고.. 이번 실험은 그 정체를 확인하기 위한 것이라고 합니다. 그리고 이를 통해서 얻을 수 있는 정보가 무지하게 많다는데..
암튼 돈도 시간도 인력도 많이 투자된 실험.. 뭔가 획기적인 결과를 얻었으면 합니다.

이 실험을 통해서 에반겔리온에서 나오는 AT필드의 비밀도 밝혀지길 기대해 봅니다.


'BlahBlah' 카테고리의 다른 글

돌고 도는 세상  (0) 2008.12.30
서태지심포니 D-day  (6) 2008.09.27
4베이 세상..  (0) 2008.05.16
눈의 피로 풀기  (0) 2007.09.17
아이리버 NV  (1) 2007.08.20
Posted by noenemy
,

요즘 쓰는 이펙터

Guitar 2008. 9. 11. 00:46

요즘 합주때 사용하는 이펙터입니다.
1년 넘게 진공관 앰프 게인에 Boss SD-1만 달랑 사용하고 있었는데...
솔로시 부스터로 쓰려고 얼마전에 Ibanez TS-9을 중고로 들여놨습니다.

TS-9을 사기 위해 집 방구석에 있던 Mobster를 다른 분게 보내야 했지요..
이펙터 사고 파는 재미도 쏠쏠 합니다.
뮬 사이트를 모니터링 하고 있다가 사려던 물건의 매물이 올라오면 바로 질러야죠.
다행히도 뮬에서 뜨는 중고매물은 직장인 분들로부터 강남쪽에서 직거래로 구입하기가 쉬워서..
그리고 복잡한 과정을 거치지 않아도 1-2주 내면 대게 원하는 모델을 구할 수 있습니다.

사용자 삽입 이미지

[사진] Ibanez TS-9(좌)과 Boss SD-1(우)


 TS-9을 모니터링한 지 1주일 쯤 되었을 때.. 매물이 올라오자 마자 이 녀석을 넘겨 받았네요.

TS-9은 드라이브를 0으로 뒀을 때나 최대로 올렸을 때나 크게 차이가 없습니다.
그 정도로 약한 게인.. 거기다 레벨을 최대로 올려도 크게 볼륨이 크다는 느낌이 없습니다.

예전 같았으면 쳐다보지도 않았을 꾹꾹이인데..
요즘 합주실에는 대부분 진공관 앰프가 있다보니 그런 앰프에 물려보면 진가를 발휘합니다.
그리고 최근에 합주하는 곡들은 모던락이나 말랑말랑한 곡들이 많다보니.. 디스토션 톤을 그다지 쓰지도 않구요.

암튼 현재는 부스터로 솔로시에 사용하고 있는데..
좀 더 연구해 보면 더 좋은 조합을 찾을 수도 있겠네요.

SD-1과 TS-9은 오래오래 함께 지낼 것 같습니다. :)



'Guitar' 카테고리의 다른 글

Pleasantly Blue 공연(3/26)  (3) 2008.10.22
지옥의 기타 트레이닝..  (0) 2008.04.03
3/20 Heroes 밴드 공연을 마치고..  (0) 2008.03.20
Heroes band rocks!!  (2) 2008.03.12
엠밴드 멤버모집 포스터  (6) 2007.12.07
Posted by noenemy
,
제가 한강변에 약간 고지대에 살고 있다 보니.. 집에서 한강을 볼 수 있답니다.

그동안 집 떠나 서울에서 객지 생활하면서
반지하에서 출발해서 기숙사, 고시원, 재건축 철거전 빌라에도 살아보고 했습니다만..
객지생활 10년이 지나 요즘 겨우 사람답게 살고 있네요.

가끔 잔잔한 음악과 함께 커피 한 잔을 들고.. 발코니에서 한강 야경을 보면서 휴식을 취하곤 합니다.

아래는 거실 발코니에서 바라다 본 한강의 모습.
멀리 남산 타워, 가까이는 한강대교와 노들섬. 그 너머에는 한참 개발 중인 용산입니다.

사용자 삽입 이미지

그리고 아래는 안방 발코니에서 바라다본 모습.
63 빌딩과 여의도 고수부지의 모습이 보입니다.

사용자 삽입 이미지

밤에 퇴근해서 집에 오면 샤워하고 바로 쓰러지는 날이 많지만..
어쩌다가 일찍 퇴근하는 날에는 이렇게 노을지는 한강의 모습을 볼 수 있네요.

바쁘고 건조하고 메마른 서울 생활이지만..
가끔 고개를 들어 높이 보면 서울의 아름다운 모습을 느낄 수 있을 겁니다.

'Picture' 카테고리의 다른 글

일산호수공원  (0) 2008.08.03
여의도불꽃축제  (1) 2007.10.15
Mark와 David을 만나다.  (2) 2007.07.26
화창한 주말. 노들섬 주변의 모습  (2) 2007.06.09
시그마 30mm f1.4의 후핀 증상과 서비스센터의 문제  (4) 2007.05.17
Posted by noenemy
,

일산호수공원

Picture 2008. 8. 3. 22:13

더위를 피하려 나들이 삼아 일산호수공원을 찾았습니다..

구름 한 점 없고.. 태양빛은 더할 나위 없이 뜨거웠기에.
일산 호수는 더위를 식혀주지 못했습니다.

센트럴파크가 부럽지 않을 정도로 잘 꾸며져 있고.. 생각보다 넓은 곳이더군요.

이 곳이 군사적인 목적으로 만들어졌다고 하는데 그게 사실일까요..
북한 정권 붕괴시 탈북자들을 이곳 이남지역으로 이동하는 것을 막기 위함이라는 신문기사를 최근에 읽은 적이 있거든요..

사용자 삽입 이미지

사용자 삽입 이미지

사용자 삽입 이미지

사용자 삽입 이미지

사용자 삽입 이미지

날씨 시원해지면 자전거 타러 다시 와야겠네요.
:)

Posted by noenemy
,

충남 보령의 미스터리 서클..
코엑스를 배경으로한 UFO 동영상..
강원도의 흉가에서 음악 작업 중이라는 소식도 들리고..

4년만에 8집으로 컴백이라..
예전 X세대들 또 다시 뭉칠 때가 된 것인가. :)



자주 볼 수 없어서 아쉽지만..
매번 기대를 져버리지 않는 새롭고 완성도 높은 음악으로 찾아 오기에
이번 8집도 많은 기대를 가져 본다.

8집 발매일 : 2008년 7월 29일
보다 멋진 티저 동영상은 www.seotaiji.com 프론트 페이지에서 볼 수 있다..


'Jukebox > Videobox' 카테고리의 다른 글

Cemetery Gates / Dream Theater  (1) 2008.04.21
Perfect / Smashing Pumpkins  (2) 2008.04.09
Metropolis Pt1 키보드 연주 모습  (2) 2007.11.13
Tarantula / Smashing Pumpkins  (0) 2007.11.01
Across the Universe / The Beatles  (0) 2007.09.18
Posted by noenemy
,