맨위로가기

Win32 스레드 정보 블록

"오늘의AI위키"는 AI 기술로 일관성 있고 체계적인 최신 지식을 제공하는 혁신 플랫폼입니다.
"오늘의AI위키"의 AI를 통해 더욱 풍부하고 폭넓은 지식 경험을 누리세요.

1. 개요

Win32 스레드 정보 블록(TIB)은 윈도우 운영체제에서 각 스레드에 대한 정보를 담는 자료 구조이다. TIB는 32비트(x86) 시스템에서는 FS 세그먼트 레지스터, 64비트(x64) 시스템에서는 GS 세그먼트 레지스터를 통해 접근하며, 스레드별 예외 처리 체인, 스레드 로컬 스토리지(TLS) 등에 대한 포인터를 포함한다. TIB는 스택 정보, GDI 정보, Wow64 관련 정보, 예외 코드 등 다양한 정보를 저장하며, 스택 베이스, 스택 제한 등의 필드를 통해 스택 관리에 필요한 정보를 제공한다. TIB는 인라인 어셈블리 또는 내장 함수를 사용하여 접근할 수 있으며, 윈도우 SDK를 통해 NtCurrentTeb 함수를 사용하여 현재 스레드 정보 블록의 주소를 얻을 수 있다.

더 읽어볼만한 페이지

  • 스레드 - 멀티스레딩
    멀티스레딩은 프로세스 내에서 여러 스레드를 동시 실행하여 처리 능력을 향상시키는 기술로, 응답성 향상과 자원 공유 등의 장점이 있지만, 자원 간섭과 소프트웨어 복잡성 증가 등의 단점도 존재하며, 다양한 모델과 구현 방식, 스레드 스케줄러, 가상 머신 활성화 가능성 등을 고려해야 한다.
  • 스레드 - 동시 멀티스레딩
    동시 멀티스레딩(SMT)은 슈퍼스칼라 구조 기반으로 한 클럭 사이클 내에 여러 스레드의 명령어를 동시에 실행하여 CPU 자원 활용률을 높이는 기술이지만, 자원 경합, 성능 저하, 보안 취약점 등의 단점도 있으며, 인텔 하이퍼 스레딩이 대표적이다.
  • 마이크로소프트 API - 윈도우 API
    윈도우 API는 마이크로소프트 윈도우 운영 체제에서 응용 프로그램이 시스템 기능에 접근하도록 돕는 인터페이스 집합이며, 다양한 버전으로 발전해 왔고, 현재 Win32가 널리 사용되며, 유연성을 제공하지만 복잡하다는 단점을 보완하기 위해 다양한 래퍼 라이브러리가 개발되었다.
  • 마이크로소프트 API - WinFS
    WinFS는 마이크로소프트가 개발한 파일 시스템으로, 검색 기능 내장 및 메타데이터 관리를 통해 데이터 관리 효율성을 높이는 것을 목표로 했으나 별도 제품으로 출시되지는 못하고 핵심 기능들이 윈도우 비스타 이후 기술에 통합되었다.
Win32 스레드 정보 블록
개요
유형데이터 구조
운영체제마이크로소프트 윈도우
설명스레드 관련 정보를 저장하는 데이터 블록
구조체 정보
정의 위치winternl.h
관련 문서Thread Information Block
Thread Information Block (Windows Drivers)
상세 정보
역할마이크로소프트 윈도우 운영체제에서 스레드 관련 정보를 저장하는 데 사용되는 데이터 구조체이다.
접근 방식x86 아키텍처에서는 `FS` 세그먼트 레지스터를 통해 접근할 수 있다.
포함 정보스레드 ID, 스택 주소, 프로세스 환경 블록(PEB)에 대한 포인터 등 스레드 실행에 필요한 다양한 정보를 포함한다.
주요 사용 목적스레드의 상태 관리, 디버깅, 성능 모니터링 등 다양한 시스템 수준 작업에 활용된다.
기타 정보TEB는 커널 모드와 사용자 모드 모두에서 접근 가능하다.

2. TIB의 구조

TIB는 운영체제 및 아키텍처에 따라 구조가 달라진다.[1] Wine의 마이크로소프트 윈도우 내부 작업에 기반하여 TIB의 구조를 나타내면 아래 표와 같다.

바이트/
타입
오프셋 (32비트, FS)오프셋 (64비트, GS)윈도우 버전설명
포인터FS:[0x00]GS:[0x00]Win9x 및 NT현재 구조적 예외 처리(SEH) 프레임
포인터FS:[0x04]GS:[0x08]Win9x 및 NT스택 베이스 / 스택 하단 (높은 주소)
포인터FS:[0x08]GS:[0x10]Win9x 및 NT스택 제한 / 스택 상단 (낮은 주소)
포인터FS:[0x0C]GS:[0x18]NT`SubSystemTib`
포인터FS:[0x10]GS:[0x20]NT파이버 데이터
포인터FS:[0x14]GS:[0x28]Win9x 및 NT임의 데이터 슬롯
포인터FS:[0x18]GS:[0x30]Win9x 및 NTTEB의 선형 주소
NT 서브시스템 독립 부분의 끝; 아래는 Win32에 종속적임
포인터FS:[0x1C]GS:[0x38]NT환경 포인터
포인터FS:[0x20]GS:[0x40]NT프로세스 ID (일부 윈도우 배포판에서는 이 필드가 `DebugContext`로 사용됨)
포인터FS:[0x24]GS:[0x48]NT현재 스레드 ID
포인터FS:[0x28]GS:[0x50]NT활성 RPC 핸들
포인터FS:[0x2C]GS:[0x58]Win9x 및 NT스레드 로컬 스토리지 배열의 선형 주소
포인터FS:[0x30]GS:[0x60]NT프로세스 환경 블록 (PEB)의 선형 주소
4FS:[0x34]GS:[0x68]NT마지막 오류 번호
4FS:[0x38]GS:[0x6C]NT소유된 중요 섹션 수
포인터FS:[0x3C]GS:[0x70]NTCSR 클라이언트 스레드의 주소
포인터FS:[0x40]GS:[0x78]NTWin32 스레드 정보
124FS:[0x44]GS:[0x80]NT, WineWin32 클라이언트 정보 (NT), user32 개인 데이터 (Wine), 0x60 = LastError (Win95&98), 0x74 = LastError (WinME)
포인터FS:[0xC0]GS:[0x100]NTWow64를 위해 예약됨. Wow64의 `FastSysCall`에 대한 포인터를 포함한다.
4FS:[0xC4]GS:[0x108]NT현재 로케일
4FS:[0xC8]GS:[0x10C]NTFP 소프트웨어 상태 레지스터
216FS:[0xCC]GS:[0x110]NT, WineOS용으로 예약됨 (NT), kernel32 개인 데이터 (Wine). 여기서: FS:[0x124] 4 NT 포인터 to `KTHREAD` (ETHREAD영어) 구조체
4FS:[0x1A4]GS:[0x2C0]NT예외 코드
18FS:[0x1A8]GS:[0x2C8]NT활성화 컨텍스트 스택
24FS:[0x1BC]GS:[0x2E8]NT, Wine여유 바이트 (NT), ntdll 개인 데이터 (Wine)
40FS:[0x1D4]GS:[0x300]NT, WineOS용으로 예약됨 (NT), ntdll 개인 데이터 (Wine)
1248FS:[0x1FC]GS:[0x350]NT, WineGDI TEB 배치 (OS), vm86 개인 데이터 (Wine)
4FS:[0x6DC]GS:[0x838]NTGDI 영역
4FS:[0x6E0]GS:[0x840]NTGDI 펜
4FS:[0x6E4]GS:[0x848]NTGDI 브러시
4FS:[0x6E8]GS:[0x850]NT실제 프로세스 ID
4FS:[0x6EC]GS:[0x858]NT실제 스레드 ID
4FS:[0x6F0]GS:[0x860]NTGDI 캐시된 프로세스 핸들
4FS:[0x6F4]GS:[0x868]NTGDI 클라이언트 프로세스 ID (PID)
4FS:[0x6F8]GS:[0x86C]NTGDI 클라이언트 스레드 ID (TID)
4FS:[0x6FC]GS:[0x870]NTGDI 스레드 로케일 정보
20FS:[0x700]GS:[0x878]NT사용자 응용 프로그램을 위해 예약됨
1248FS:[0x714]GS:[0x890]NTGL용으로 예약됨 (내부 정보는 와인 참조)[1]
4FS:[0xBF4]GS:[0x1250]NT마지막 상태 값
532FS:[0xBF8]GS:[0x1258]NT정적 `UNICODE_STRING` 버퍼
포인터FS:[0xE0C]GS:[0x1478]NT`DeallocationStack`이라고도 알려져 있으며, 스택 버퍼의 실제 시작 주소를 설정하므로 실제 스택 제한을 설정한다. 이는 스택 제한 필드보다 몇 페이지 적다 (스택 오버플로를 감지하는 데 사용되는 가드 페이지를 숨긴다).
포인터[]FS:[0xE10]GS:[0x1480]NTTLS 슬롯, 슬롯당 4/8 바이트, 64 슬롯
8FS:[0xF10]GS:[0x1680]NTTLS 링크 (`LIST_ENTRY` 구조체)
4FS:[0xF18]GS:[0x1690]NTVDM
4FS:[0xF1C]GS:[0x1698]NTRPC용으로 예약됨
4FS:[0xF28]GS:[0x16B0]NT스레드 오류 모드 (`RtlSetThreadErrorMode`)
4FS:[0xF78]GS:[0x1748]NT보장된 스택 바이트
이것은 전체 표가 아니다. FS:[0xfb4] / GS:[17c8]까지의 모든 필드는 Wine 참조를 참조.[1] 최신 윈도우 버전은 TIB 크기를 윈도우 10에서 0x1000/0x1838까지 확장한다. 추가된 일부 필드는 제거되어 정의가 충돌한다.[2]



FS (32비트의 경우) 또는 GS (64비트의 경우)는 TDB (스레드 데이터베이스)로 알려진 데이터 블록에 포함된 TIB에 매핑된다. TIB에는 스레드별 예외 처리 체인과 TLS (스레드 로컬 스토리지)에 대한 포인터가 포함되어 있으며, 스레드 로컬 스토리지는 C 로컬 스토리지와는 다르다.

2. 1. 32비트 윈도우 (x86)

32비트 윈도우(x86)에서 TIB는 FS 세그먼트 레지스터를 통해 접근한다. 주요 필드는 다음과 같다:[1]

위치길이윈도우 버전설명
FS:[0x00]4Win9x 및 NT현재 구조적 예외 처리(SEH) 프레임
FS:[0x04]4Win9x 및 NT스택 베이스 / 스택의 바닥 (높은 주소)
FS:[0x08]4Win9x 및 NT스택 한계 / 스택의 천장 (낮은 주소)
FS:[0x0C]4NTSubSystemTib
FS:[0x10]4NTFiber data
FS:[0x14]4Win9x 및 NT임의 데이터 슬롯
FS:[0x18]4Win9x 및 NTThread Environment Block
---- NT subsystem 독립적인 부분 끝 ----
FS:[0x1C]4NTEnvironment Pointer
FS:[0x20]4NT프로세스 ID (몇몇 윈도우 버전에서 이 필드는 DebugContext로 쓰인다.)
FS:[0x24]4NT현재 스레드 ID
FS:[0x28]4NT활동중인 RPC 핸들
FS:[0x2C]4Win9x 및 NT스레드 로컬 스토리지 배열의 선형 주소
FS:[0x30]4NT프로세스 환경 블록(PEB)의 선형 주소
FS:[0x34]4NT마지막 오류 번호
FS:[0x38]4NT소유된 중요 섹션 수
FS:[0x3C]4NTCSR 클라이언트 스레드의 주소
FS:[0x40]4NTWin32 스레드 정보
FS:[0x44]124NT, WineWin32 클라이언트 정보 (NT), user32 private data (Wine), 0x60 = LastError (Win95), 0x74 = LastError (WinME)
FS:[0xC0]4NTWow64를 위해 예약됨. Wow64에서 FastSysCall에 대한 포인터를 포함한다.
FS:[0xC4]4NTCurrent Locale
FS:[0xC8]4NTFP Software Status Register
FS:[0xCC]216NT, WineOS용으로 예약됨 (NT), kernel32 private data (Wine). herein: FS:[0x124] 4 NT Pointer to KTHREAD (ETHREAD) structure
FS:[0x1A4]4NT예외 코드
FS:[0x1A8]18NTActivation context stack
FS:[0x1BC]24NT, WineSpare bytes (NT), ntdll private data (Wine)
FS:[0x1D4]40NT, WineOS용으로 예약됨 (NT), ntdll private data (Wine)
FS:[0x1FC]1248NT, WineGDI TEB Batch (OS), vm86 private data (Wine)
FS:[0x6DC]4NTGDI Region
FS:[0x6E0]4NTGDI 펜
FS:[0x6E4]4NTGDI 브러시
FS:[0x6E8]4NTReal Process ID
FS:[0x6EC]4NTReal Thread ID
FS:[0x6F0]4NTGDI cached process handle
FS:[0x6F4]4NTGDI 클라이언트 프로세스 ID (PID)
FS:[0x6F8]4NTGDI 클라이언트 스레드 ID (TID)
FS:[0x6FC]4NTGDI thread locale information
FS:[0x700]20NT사용자 응용 프로그램을 위해 예약됨
FS:[0x714]1248NTGL용으로 예약됨
FS:[0xBF4]4NT마지막 상태 값
FS:[0xBF8]532NTStatic UNICODE_STRING buffer
FS:[0xE0C]4NTdeallocation stack에 대한 포인터
FS:[0xE10]256NTTLS 슬롯, 슬롯 당 4 byte
FS:[0xF10]8NTTLS 링크 (LIST_ENTRY structure)
FS:[0xF18]4NTVDM
FS:[0xF1C]4NTRPC용으로 예약됨
FS:[0xF28]4NT스레드 에러 모드(RtlSetThreadErrorMode)


2. 2. 64비트 윈도우 (x64)

64비트 윈도우에서 TIB는 GS 세그먼트 레지스터를 통해 접근한다.[1] 32비트 구조와 유사하지만, 필드의 크기와 오프셋이 다르다. 다음은 Wine의 마이크로소프트 윈도우 내부 작업에 기반한 64비트 TIB 구조이다.[1]

바이트/타입오프셋 (64비트, GS)윈도우 버전설명
포인터GS:[0x00]Win9x 및 NT현재 구조적 예외 처리(SEH) 프레임
포인터GS:[0x08]Win9x 및 NT스택 베이스 / 스택 하단 (높은 주소)
포인터GS:[0x10]Win9x 및 NT스택 제한 / 스택 상단 (낮은 주소)
포인터GS:[0x18]NTSubSystemTib
포인터GS:[0x20]NT파이버 데이터
포인터GS:[0x28]Win9x 및 NT임의 데이터 슬롯
포인터GS:[0x30]Win9x 및 NTTEB의 선형 주소
NT 서브시스템 독립 부분의 끝; 아래는 Win32에 종속적임
포인터GS:[0x38]NT환경 포인터
포인터GS:[0x40]NT프로세스 ID (일부 윈도우 배포판에서는 이 필드가 DebugContext로 사용됨)
포인터GS:[0x48]NT현재 스레드 ID
포인터GS:[0x50]NT활성 RPC 핸들
포인터GS:[0x58]Win9x 및 NT스레드 로컬 스토리지 배열의 선형 주소
포인터GS:[0x60]NT프로세스 환경 블록 (PEB)의 선형 주소
4GS:[0x68]NT마지막 오류 번호
4GS:[0x6C]NT소유된 중요 섹션 수
포인터GS:[0x70]NTCSR 클라이언트 스레드의 주소
포인터GS:[0x78]NTWin32 스레드 정보
124GS:[0x80]NT, WineWin32 클라이언트 정보 (NT), user32 개인 데이터 (Wine), 0x60 = LastError (Win95&98), 0x74 = LastError (WinME)
포인터GS:[0x100]NTWow64를 위해 예약됨. Wow64의 FastSysCall에 대한 포인터를 포함한다.
4GS:[0x108]NT현재 로케일
4GS:[0x10C]NTFP 소프트웨어 상태 레지스터
216GS:[0x110]NT, WineOS용으로 예약됨 (NT), kernel32 개인 데이터 (Wine)
여기서: 4 NT 포인터 to KTHREAD (ETHREAD) 구조체
4GS:[0x2C0]NT예외 코드
18GS:[0x2C8]NT활성화 컨텍스트 스택
24GS:[0x2E8]NT, Wine여유 바이트 (NT), ntdll 개인 데이터 (Wine)
40GS:[0x300]NT, WineOS용으로 예약됨 (NT), ntdll 개인 데이터 (Wine)
1248GS:[0x350]NT, WineGDI TEB 배치 (OS), vm86 개인 데이터 (Wine)
4GS:[0x838]NTGDI 영역
4GS:[0x840]NTGDI 펜
4GS:[0x848]NTGDI 브러시
4GS:[0x850]NT실제 프로세스 ID
4GS:[0x858]NT실제 스레드 ID
4GS:[0x860]NTGDI 캐시된 프로세스 핸들
4GS:[0x868]NTGDI 클라이언트 프로세스 ID (PID)
4GS:[0x86C]NTGDI 클라이언트 스레드 ID (TID)
4GS:[0x870]NTGDI 스레드 로케일 정보
20GS:[0x878]NT사용자 응용 프로그램을 위해 예약됨
1248GS:[0x890]NTGL용으로 예약됨 (내부 정보는 와인 참조)[1]
4GS:[0x1250]NT마지막 상태 값
532GS:[0x1258]NT정적 UNICODE_STRING 버퍼
포인터GS:[0x1478]NTDeallocationStack이라고도 알려져 있으며, 스택 버퍼의 실제 시작 주소를 설정하므로 실제 스택 제한을 설정한다. 이는 스택 제한 필드보다 몇 페이지 적다 (스택 오버플로를 감지하는 데 사용되는 가드 페이지를 숨긴다).
포인터[]GS:[0x1480]NTTLS 슬롯, 슬롯당 4/8 바이트, 64 슬롯
8GS:[0x1680]NTTLS 링크 (LIST_ENTRY 구조체)
4GS:[0x1690]NTVDM
4GS:[0x1698]NTRPC용으로 예약됨
4GS:[0x16B0]NT스레드 오류 모드 (RtlSetThreadErrorMode)
4GS:[0x1748]NT보장된 스택 바이트
이것은 전체 표가 아니다. GS:[0x17c8]까지의 모든 필드는 Wine 참조를 참조.[1] 최신 윈도우 버전은 TIB 크기를 윈도우 10에서 0x1838까지 확장한다. 추가된 일부 필드는 제거되어 정의가 충돌한다.[2]


2. 3. 추가 정보

TIB에는 다음과 같은 다양한 정보들이 포함되어 있다.[1]

  • GDI 정보
  • Wow64 관련 정보
  • 예외 코드
  • 활성화 컨텍스트 스택


32비트 (FS)64비트 (GS)설명
0x1A40x2C0예외 코드
0x1A80x2C8활성화 컨텍스트 스택
0x1FC0x350GDI TEB 배치
0x6DC0x838GDI 영역
0x6E00x840GDI 펜
0x6E40x848GDI 브러시
0x6E80x850실제 프로세스 ID
0x6EC0x858실제 스레드 ID
0x6F00x860GDI 캐시된 프로세스 핸들
0x6F40x868GDI 클라이언트 프로세스 ID (PID)
0x6F80x86CGDI 클라이언트 스레드 ID (TID)
0x6FC0x870GDI 스레드 로케일 정보
0xC00x100Wow64를 위해 예약됨. Wow64의 FastSysCall에 대한 포인터를 포함.
0x7140x890GL용으로 예약됨 (내부 정보는 와인 참조)[1]


3. TIB 접근 방법

현재 스레드의 TIB는 세그먼트 레지스터 FS (x86) 또는 GS (x64)의 오프셋으로 접근할 수 있다.[3]

일반적으로 `FS:[0x18]`(32비트) 또는 `GS:[0x30]`(64비트)에 있는 선형 자기 참조 포인터를 사용하여 TIB에 접근한다. 이 포인터를 포인터 연산에 사용하거나 구조체 포인터로 캐스팅할 수 있다.

마이크로소프트 윈도우 SDK를 사용하는 경우, `winnt.h`에 정의된 인라인 함수 `NtCurrentTeb`를 사용하여 현재 스레드 정보 블록의 주소를 `NT_TIB *` 형태로 얻을 수 있다.[3]

C/C++ 코드에서는 인라인 어셈블리 또는 내장 함수를 사용하여 TIB에 접근할 수 있다. (자세한 내용은 하위 섹션 "코드 예제 (C/C++)" 참고)

3. 1. 코드 예제 (C/C++)

cpp

// gcc (AT&T 스타일 인라인 어셈블리).

void *getTIB(void) {

register void *pTIB;

#if defined(__x86_64__) || defined(__amd64__)

__asm__("movq %%gs:0x30, %0" : "=r" (pTIB));

#elif defined(__i386__)

__asm__("movl %%fs:0x18, %0" : "=r" (pTIB));

#else

#error unsupported architecture

#endif

return pTIB;

}

```

```cpp

// gcc (이름 지정된 주소 공간, -O1 또는 -ftree-ter에서 인라인 어셈블리 버전과 동일).

void *getTIB(void) {

#if defined(__x86_64__) || defined(__amd64__)

#ifndef __SEG_GS

#error unsupported GCC version

#endif

return *(void *__seg_gs *) 0x30;

#elif defined(__i386__)

#ifndef __SEG_FS

#error unsupported GCC version

#endif

return *(void *__seg_fs *) 0x18;

#else

#error unsupported architecture

#endif

}

```

```cpp

// Microsoft C

__declspec(naked)

void *getTIB() {

__asm mov EAX, FS:[18h]

__asm ret

}

```

```cpp

// 인라인 어셈블리 대신 Microsoft의 내장 함수 사용 (X86 및 X64 아키텍처 모두에서 작동).

void *getTIB() {

#ifdef _M_IX86

return (void *)__readfsdword(0x18);

#elif _M_AMD64

return (void *)__readgsqword(0x30);

#else

#error unsupported architecture

#endif

}

4. 스택 정보

프로세스는 TIB에 저장된 정보를 적절하게 업데이트하는 한, 스레드의 스택을 자유롭게 이동할 수 있어야 한다. 이와 관련하여 몇 가지 중요한 필드가 있는데, 이는 스택 베이스, 스택 제한, 할당 해제 스택 및 보장된 스택 바이트이며, 각각 64비트에서 오프셋 `0x8`, `0x10`, `0x1478` 및 `0x1748`에 저장된다.[1] 다양한 Windows 커널 함수는 이러한 값을 읽고 쓰는데, 특히 스택 오버플로를 다른 읽기/쓰기 페이지 폴트와 구별하기 위해 사용된다 (보장된 스택 바이트 내에서 스택 제한에 의해 보호되는 페이지에 대한 읽기 또는 쓰기는 액세스 위반 대신 스택 오버플로 예외를 발생시킨다).[1] 할당 해제 스택은 Windows API가 보호된 페이지의 양을 변경할 수 있기 때문에 중요하다.[1] `SetThreadStackGuarantee` 함수는 현재 공간을 읽고 이를 늘릴 수 있게 해준다.[1] 읽으려면 `GuaranteedStackBytes` 필드를 읽고, 늘리려면 스택 페이지를 언커밋해야 한다.[1] `DeallocationStack`을 설정하지 않고 스택 제한을 설정하면 `SetThreadStackGuarantee`에서 이상한 동작이 발생할 수 있다.[1] 예를 들어, 스택 제한이 잘못된 값으로 덮어쓰여질 수 있다.[1] 다양한 라이브러리에서 `SetThreadStackGuarantee`를 호출하는데, 예를 들어 .NET CLR은 스레드의 스택을 설정하는 데 사용한다.[1]

참조

[1] 웹사이트 wine winternl.h: typedef struct _TEB https://github.com/w[...] wine-mirror 2019-10-29
[2] 웹사이트 TEB https://www.geoffcha[...]
[3] 웹사이트 NtCurrentTeb function https://docs.microso[...] 2019-11-20



본 사이트는 AI가 위키백과와 뉴스 기사,정부 간행물,학술 논문등을 바탕으로 정보를 가공하여 제공하는 백과사전형 서비스입니다.
모든 문서는 AI에 의해 자동 생성되며, CC BY-SA 4.0 라이선스에 따라 이용할 수 있습니다.
하지만, 위키백과나 뉴스 기사 자체에 오류, 부정확한 정보, 또는 가짜 뉴스가 포함될 수 있으며, AI는 이러한 내용을 완벽하게 걸러내지 못할 수 있습니다.
따라서 제공되는 정보에 일부 오류나 편향이 있을 수 있으므로, 중요한 정보는 반드시 다른 출처를 통해 교차 검증하시기 바랍니다.

문의하기 : help@durumis.com