16. 스레드 스택
제프리 리처의 Windows via C/C++
김형주
스레드 스택
1. C/C++ 런타임 라이브러리의 스택 확인 함수
2. Summation 예제 애플리케이선
• 스레드가 생성되면 시스템은 프로세스의 주소 공간에 스레드 스택으로 사용할 영역을 예약
• 이 영역에 물리적 저장소를 일부 커밋
• 각각의 스레드는 자신만의 스택을 가진다
• 기본적으로 시스템은 1MB 의 주소 공간을 예약하고 이 중 물리적 저장소로 두 개의 페이지를 커밋
• 기본 설정은 마이크로소프트 C++ 컴파일러의 /F 옵션이나 마이크로소프트 링커의 /STACK 옵션으로 변경 가능
• CreateThread나 _ beginthreadex 함수 호출 할 때 커밋할 물리적 저장소의 크기 전달 가능
스레드 스택
Initflag 매개변수에 플래그를 지정하지 않으면
stack_size 는 커밋 크기를 지정
0으로 지정하면 시스템은 PE 헤더에
지정된 크기를 이용하여 물리적 저장소를 커멋
• 그림은 4KB 의 페이지를 사용하는 스택으로 예약된 영역 표현
• 스택 영역과 커밋된 물리적 저장소 모두 PAGE_READWRITE 보호 특성
• 예약 영역은 0x08000000으로부터 시작
• 예약된 영역 최상위 두 개의 페이지에 물리적 저장소를 커밋
• 스레드의 스택 포인터 레지스터는 예약된 영역의 최상위 페이지 끝을
(0x08100000)을 가리키도록 설정(스택을 사용할 때의 시작 위치)
스레드 스택 영역
• 스택 영역의 두 번째 페이지는 가드 페이지(guard page)
• 스레드가 함수를 계속 호출하면 호출 트리(call tree) 깊이 증가, 더 많
은 스택 공간 필요
• 스레드가 가드 페이지에 접근을 시도하게 되면,
• 시스템은 가드 페이지 이하에 추가적으로 페이지를 커밋,
• 현재 가드 페이지의 가드 페이지 보호 특성 해제
• 새롭게 커빗된 페이지에 대해 가드페이지 보호특성 설정
• 이를 통해 필요로 하는 크기에 맞게 스택의 물리적 저장소를 증가
• 스레드의 호출 트리가 계속해서 깊어지면 스택 영역은 [그림 16-2]와
같이 변경될 것이다.
가드 페이지
• 스레드의 호출 트리가 계속해서 깊어지면 스택 영역은 아래와 같이 변경
가드 페이지
• 0x8001000 페이지에 물리적 저장소 커밋할 때는 새로 커밋한 저장소에 대해 가드 보호 특성을 지정하지 않음
• 이것은 스택으로 예약된 주소 공간이 모두 물리적 저장소로 커밋되었다는 것을 의미
• 시스템은 0x08001000에 커밋할 때는 0xC00000FD로 정의되어 있는 EXCEPTION_STACK_OVERFLOW 예외 유발
• 구조적 예외 처리(SEH)를 이용하면 프로그램은 현재 상황에 대한 통지를 받을 수 있고, 예외 상황을 처리
스레드 스택 영역의 사용
• 스택 오버플로가 발생한 이후 스레드가 계속 스택을 사용하면 결국 0x08000000으로 시작하는 페이지도 접근
• 그럴 경우 시스템은 스레드가 심각한 에러 상황에 직면한 것으로 판단하고 접근 위반 예외를 유발
• 이러한 예외 상황이 발생하게 되면 시스템은 윈도우 에러 보고 서비스로 제어권을 전달하여 프로세스가 종료되기
전에 다음과 같은 다이얼로그 박스를 화면에 출력
• 시스템은 스택 영역의 최하위 페이지를 예약상태로 유지해서 스레드가 이 페이지에 접근하는 사실을 알 수 있다
• 이를 이용하여 프로세스가 사용하는 다른 데이터들이 실수로 덮어 쓰여지는 것을 막을 수 있다.
접근 위반 예외
• 함수가 배열에 대한 할당문을 수행하게 되면 스택의 끝을 초과
• 스택의 끝을 초과한 영역이 이미 다른 용도로 사용되는 경우라면 접근 위반 예외를 발생시키지 못함
스택 언더플로
• 오른쪽 코드는 스택 언더플로가 발생하는
경우 항상 데이터의 손실을 유발
스택 언더플로
• C/C++ 런타임 라이브러리에는 스택 확인 함수 존재
• 컴파일러는 스택 확인이 필요한 곳에 자동적으로 함수를 호출하도록 코드를 포함
• 스택 확인 함수는 스레드 스택으로 사용되는 영역에 물리적 저장소가 적절히 커밋되었는지 확인하는 역할
• 함수는 16,000 바이트의 공간을 정수형 배열로 사용
• 16 000바이트의 스택 공간을 할당은 단순히 CPU의 스택 포인터 값으로부터 16,000바이트를 빼는 작업
• 시스템은 이 영역에 대한 실질적인 접근이 이루어지기 전까지는 물리적 저장소를 커밋하지 않는다.
• 가드 페이지보다 더 아래에 있는 스택에 접근하면, 예약만 수행된 메모리에 대한 접근으로 접근 예외 발생
C/C++ 런타임 라이브러리의 스택 확인 함수
• 컴파일 과정에서 각 함수들의 스택의 크기를 결정
• 함수가 필요로 하는 스택의 크기가 개별 CPU의 페이지 보
다 더 큰 메모리를 필요로 하는 경우, 컴파일러는 자동적으
로 스택 확인 함수를 호출하는 코드를 삽입
• 오른쪽의 슈도코드는 스택 확인 함수의 작업 설명
C/C++ 런타임 라이브러리의 스택 확인 함수
• Summation 예제는 0부터 사용자가 입력하는 X까지의 합을 구해준다
Summation 예제 애플리케이션
16 스레드 스택
16 스레드 스택
16 스레드 스택
16 스레드 스택

16 스레드 스택

  • 1.
    16. 스레드 스택 제프리리처의 Windows via C/C++ 김형주
  • 2.
    스레드 스택 1. C/C++런타임 라이브러리의 스택 확인 함수 2. Summation 예제 애플리케이선
  • 3.
    • 스레드가 생성되면시스템은 프로세스의 주소 공간에 스레드 스택으로 사용할 영역을 예약 • 이 영역에 물리적 저장소를 일부 커밋 • 각각의 스레드는 자신만의 스택을 가진다 • 기본적으로 시스템은 1MB 의 주소 공간을 예약하고 이 중 물리적 저장소로 두 개의 페이지를 커밋 • 기본 설정은 마이크로소프트 C++ 컴파일러의 /F 옵션이나 마이크로소프트 링커의 /STACK 옵션으로 변경 가능 • CreateThread나 _ beginthreadex 함수 호출 할 때 커밋할 물리적 저장소의 크기 전달 가능 스레드 스택 Initflag 매개변수에 플래그를 지정하지 않으면 stack_size 는 커밋 크기를 지정 0으로 지정하면 시스템은 PE 헤더에 지정된 크기를 이용하여 물리적 저장소를 커멋
  • 4.
    • 그림은 4KB의 페이지를 사용하는 스택으로 예약된 영역 표현 • 스택 영역과 커밋된 물리적 저장소 모두 PAGE_READWRITE 보호 특성 • 예약 영역은 0x08000000으로부터 시작 • 예약된 영역 최상위 두 개의 페이지에 물리적 저장소를 커밋 • 스레드의 스택 포인터 레지스터는 예약된 영역의 최상위 페이지 끝을 (0x08100000)을 가리키도록 설정(스택을 사용할 때의 시작 위치) 스레드 스택 영역
  • 5.
    • 스택 영역의두 번째 페이지는 가드 페이지(guard page) • 스레드가 함수를 계속 호출하면 호출 트리(call tree) 깊이 증가, 더 많 은 스택 공간 필요 • 스레드가 가드 페이지에 접근을 시도하게 되면, • 시스템은 가드 페이지 이하에 추가적으로 페이지를 커밋, • 현재 가드 페이지의 가드 페이지 보호 특성 해제 • 새롭게 커빗된 페이지에 대해 가드페이지 보호특성 설정 • 이를 통해 필요로 하는 크기에 맞게 스택의 물리적 저장소를 증가 • 스레드의 호출 트리가 계속해서 깊어지면 스택 영역은 [그림 16-2]와 같이 변경될 것이다. 가드 페이지
  • 6.
    • 스레드의 호출트리가 계속해서 깊어지면 스택 영역은 아래와 같이 변경 가드 페이지
  • 7.
    • 0x8001000 페이지에물리적 저장소 커밋할 때는 새로 커밋한 저장소에 대해 가드 보호 특성을 지정하지 않음 • 이것은 스택으로 예약된 주소 공간이 모두 물리적 저장소로 커밋되었다는 것을 의미 • 시스템은 0x08001000에 커밋할 때는 0xC00000FD로 정의되어 있는 EXCEPTION_STACK_OVERFLOW 예외 유발 • 구조적 예외 처리(SEH)를 이용하면 프로그램은 현재 상황에 대한 통지를 받을 수 있고, 예외 상황을 처리 스레드 스택 영역의 사용
  • 8.
    • 스택 오버플로가발생한 이후 스레드가 계속 스택을 사용하면 결국 0x08000000으로 시작하는 페이지도 접근 • 그럴 경우 시스템은 스레드가 심각한 에러 상황에 직면한 것으로 판단하고 접근 위반 예외를 유발 • 이러한 예외 상황이 발생하게 되면 시스템은 윈도우 에러 보고 서비스로 제어권을 전달하여 프로세스가 종료되기 전에 다음과 같은 다이얼로그 박스를 화면에 출력 • 시스템은 스택 영역의 최하위 페이지를 예약상태로 유지해서 스레드가 이 페이지에 접근하는 사실을 알 수 있다 • 이를 이용하여 프로세스가 사용하는 다른 데이터들이 실수로 덮어 쓰여지는 것을 막을 수 있다. 접근 위반 예외
  • 9.
    • 함수가 배열에대한 할당문을 수행하게 되면 스택의 끝을 초과 • 스택의 끝을 초과한 영역이 이미 다른 용도로 사용되는 경우라면 접근 위반 예외를 발생시키지 못함 스택 언더플로
  • 10.
    • 오른쪽 코드는스택 언더플로가 발생하는 경우 항상 데이터의 손실을 유발 스택 언더플로
  • 11.
    • C/C++ 런타임라이브러리에는 스택 확인 함수 존재 • 컴파일러는 스택 확인이 필요한 곳에 자동적으로 함수를 호출하도록 코드를 포함 • 스택 확인 함수는 스레드 스택으로 사용되는 영역에 물리적 저장소가 적절히 커밋되었는지 확인하는 역할 • 함수는 16,000 바이트의 공간을 정수형 배열로 사용 • 16 000바이트의 스택 공간을 할당은 단순히 CPU의 스택 포인터 값으로부터 16,000바이트를 빼는 작업 • 시스템은 이 영역에 대한 실질적인 접근이 이루어지기 전까지는 물리적 저장소를 커밋하지 않는다. • 가드 페이지보다 더 아래에 있는 스택에 접근하면, 예약만 수행된 메모리에 대한 접근으로 접근 예외 발생 C/C++ 런타임 라이브러리의 스택 확인 함수
  • 12.
    • 컴파일 과정에서각 함수들의 스택의 크기를 결정 • 함수가 필요로 하는 스택의 크기가 개별 CPU의 페이지 보 다 더 큰 메모리를 필요로 하는 경우, 컴파일러는 자동적으 로 스택 확인 함수를 호출하는 코드를 삽입 • 오른쪽의 슈도코드는 스택 확인 함수의 작업 설명 C/C++ 런타임 라이브러리의 스택 확인 함수
  • 13.
    • Summation 예제는0부터 사용자가 입력하는 X까지의 합을 구해준다 Summation 예제 애플리케이션