PCB의 스레드 버전이다
(스레드 메타데터 묶음이란 뜻)
ID: tid
(스레드 식별자)
상태: READY / RUNNING / BLOCKED / DYING
스케줄링 정보: priority
(우선순위), 러닝타임/타임슬라이스 통계
컨텍스트 저장 위치: 스위치 시점의 커널 스택 상 프레임과 TCB의 일부 필드
큐 연결고리: 레디 큐, 대기(sema/lock) 큐에 들어갈 list node
커널 스택 포인터: 현재 스레드의 커널 스택 최상단 지시자
디버깅/가드: 스택 오버플로 감지용 magic
값 등
둘 다 스택이다
스택은 힙처럼 메모리 영역 쓰지만 좀 다르다
스택:
스레드 생성 시 OS/런타임이 스레드별로 영역을 예약(+가드 페이지1) 함수 호출/리턴에 따라 자동으로 push/pop
힙:
프로세스 전체에 1개. malloc/free(또는 new/delete) 같은 명시적 호출로 관리
당연하면 당연하게도 커널 코드가 사용하기 위한 스택이다
정확히는 스레드가 커널 모드로 들어오는 동안 사용한다
TCB와 같은 페이지에 배치되는게 전형적인 구조다
+-------------------------+ 높은 주소
| 커널 스택 (아래로 성장) |
| ... |
| saved context frames | ← 컨텍스트 스위치 시 push되는 곳
+-------------------------+
| struct thread | ← TCB, magic이 여기 있음
+-------------------------+ 낮은 주소 (4KiB 한 페이지)
유저모드에서 커널 진입(시스템콜/인터럽트) 시 CPU가 스택을 바꿔 커널 스택 사용한다
스케줄러가 다른 스레드로 바꿀 때, 현재 커널 스택 프레임에 레지스터/리턴지점을 저장하고,
다음 스레드의 stack
(커널 스택 top)을 로드하여 복원
보통 한 스레드당 한 페이지 (4KiB) 로 앙증 맞다
그러니 큰 배열/구조체는 커널 스택말고 동적 할당 등으로 처리하자
⌜Ring 0⌟
OS 커널이 실행되는 최고 권한 모드다
못하는게 없다
커널 스택은 커널 모드에서 썼으니
유저 스택은 유저 모드에서 쓴다
유저 프로그램 코드를 실행할 때 C 함수 호출 스택으로 쓰인다
고정/제한적일 떄도 있으나 보통 지연 확장(스택 자동 성장) 을 구현한다
Ring 3
일반 프로그램 실행되는 제한된 권한 모드
위험한 일(금지된 명령, 커널 메모리 접근) 못한다
보통 스택 끝에 붙여둬 스택 넘치는 거 관리한다
“접근 금지”로 표시해 둔 메모리 페이지
↩