스레드 ( Thread )
- 프로세스를 사용하는 문제점을 해결하기 위해서 고안되었다.
- 프로세스보다 더 작은 실행단위로 형대 운영체제가 작업을 스케줄링 하는 단위이다.
장점 : 빠른 Context Switching, 스레드간 쉬운 통신, 프로세스 생성 및 소멸에 따른 오버헤드 감소
프로세스와 스레드의 관계
"프로세스는 스레드들을 보관하는 컨테이너, 스레드는 프로세스의 함수"
- 프로세스가 생성될 때, OS에 의해 자동으로 mainThread가 생성된다.
- 하나의 프로세스는 여러 스레드를 가질 수 있다.
- 스레드는 각각의 TCB를 생성하고, PCB에 등록한다.
- 모든 스레드는 프로세스의 코드, 데이터, 힙을 공유하기에 스레드간 통신이 용이하다.
단, 스택은 별도의 공간을 사용한다.
- 스레드의 종료 -> TCB가 제거되고, 모든 스레드가 종료되면 프로세스가 종료된다.
- 프로세스를 강제종료할 경우에, 내부 스레드들도 모두 종료된다.
단, 스레드의 실행 순서를 알 수 없으므로, 하나의 자원을 여러 스레드가 접근하려고 할 때의 해결법을 마련해야 한다.
스레드 주소 공간
- 스레드가 생성, 실행되는 동안 접근 가능한 메모리 영역
- 스레드 주소 공간은 프로세스의 주소 공간 내에 형성된다.
- 스레드 사적 공간 : Thread Code, TLS(Thread Local Storage), Stack
- 스레드 공유 공간 : Process Code, Process Data(로컬 데이터 제외), Process Heap
- 스레드 LifeCycle : Ready, Running, Waiting, Terminated
Thread Operation
- 스레드 생성
스레드가 생성하는 시스템 호출이나 라이브러리 함수를 호출해 스레드를 생성할 수 있다.
프로세스가 생성되면 자동으로 mainThread 생성
- 스레드 종료
프로세스에 속한 아무 스레드라도 exit()호출 시, 프로세스+모든스레드 종료
메인스레드가 종료되면 모든 스레드가 종료된다. ( 프로세스도 종료됨 )
pthread_exit()와 같이 현재 스레드만 종료하는 함수도 있다. ( main에서 사용해도 모든 스레드 종료 X )
- 스레드 조인
스레드가 다른 스레드가 종료할 때 까지 대기. ( 주로 부모 스레드가 자식 스레드의 종료를 기다린다. )
- 스레드 양보 (yield)
스레드가 자발적으로 yield()같은 함수 호출을 통해 실행을 중단하여 다른 스레드를 스케줄하게 된다.
Thread Context
- 스레드의 실행중인 상태 정보는 TCB에 저장되며, TCB는 스레드가 생성될 때 커널에 의해 만들어진다.
- TCB는 스레드 소멸 때 같이 사라지며, 각종 CPU 레지스터들의 값을 관리한다.
-> PC, SB/BP(스택 정보), Flag(CPU 상태) 등...
Thread Context Switching
- CPU 레지스터 저장 및 복귀
현재 실행중인 스레드 A의 Context를 TCB-A에 저장하고, TCB-B의 Context를 CPU에 적재한다.
CPU는 스레드 B가 이전에 중단된 위치를 기억해 실행 재개, SP 레지스터 복귀로 이전 스택을 찾는다.
스택에는 이전에 중단될 때 실행하던 함수의 매개변수, 지역변수가 그대로 저장되어 있다.
- 커널 정보 수정
TCB-A, TCB-B의 스레드 상태 정보, CPU 사용시간 등을 수정한다.
TCB-A를 Ready list에서 Block list로 옮기고, TCB-B를 Ready list에서 분리한다.
Overhead in Context Switching
- Context switch는 상당히 비싼 연산으로, CPU의 시간을 소모한다. ( 자주하면 컴퓨터 처리율이 저하된다. )
- 동일 프로세스 내 스위칭 : Context 저장 및 복귀 , TCB 리스트 조작, 캐시 Flush & Fill
- 다른 프로세스와 스위칭 : CPU 주소공간 변화로 추가 오버헤드, 매핑테이블 교체로 추가. ( Memory Overhead )
멀티 스레딩 모델
1. User-level Thread
- 사용자 스레드 : 라이브러리에 의해 구현된 일반적인 스레드.
- 응용프로그램이 생성, 스레드 라이브러리가 스레드 정보(U-TCB)를 사용자 공간에 생성하고 소유한다.
- 커널은 유저레벨 스레드를 하나의 프로세스로 인식하며, 스레드 공간은 사용자 공간에 둔다.
2. Kernel-level Thread
- 커널 스레드 : 커널이 직접 생성하고 관리하는 스레드
- 응용프로그램이 시스템 호출을 통해 생성, 커널이 TCB 소유 및 스케줄링 한다.
- main 스레드는 커널 스레드, 스레드 주소공간은 사용자 공간에 둔다.
순수 커널 레벨 스레드 : 부팅 때부터 커널의 기능을 돕기 위해 만들어진 스레드, 스레드 주소공간은 커널에 둔다.
-> 유저 모드에서 실행되는 일 X
멀티스레드의 구현
- 응용 프로그램에서 작성한 스레드가 시스템에서 실행되게 구현하며,
- 스레드 라이브러리와 커널의 시스템 호출의 상호 협력이 필요하다.
- N:1 ( N개 유저레벨 - 1개 커널레벨 ), 1:1 ( 1개 유저레벨 - 1개 커널레벨 ), N:M ( N개 유저레벨 - M개 커널레벨 )
fork() : 새로운 프로세스는 fork()를 호출한 스레드만 복제된다.
exec() : 한 스레드가 exec()를 실행하면, 프로세스 전체가 사라진다.
-> fork() 이후 exec()를 실행 시, 모든 스레드가 복제될 이유가 없다. exec()를 실행하지 않으면 복제할 이유가 있음.
Thread-Safe
- 멀티 스레드 프로그램에서 어떤 자원에 대해 여러 스레드에서 동시 접근해도 실행에 문제가 없어야한다.
Re-entrancy : 동시에 접근해도 결과가 올바르게 나와야함.
Thread-local Storage : 공유자원 사용을 줄여 동시 접근을 막음. ( 공유상태의 회피가 힘들 때 사용 )
Mutual Exclusion : 자원의 접근을 세마포등의 락으로 통제함.
Atomic Operation : 원자적 접근으로 상호 배제를 구현함.
'3-1공부 > 운영체제' 카테고리의 다른 글
7. 스케줄링 알고리즘 (0) | 2022.04.19 |
---|---|
6. 스케줄링 (0) | 2022.04.19 |
4. 프로세스 (0) | 2022.04.18 |
3. 컴퓨터 구조 (0) | 2022.04.18 |
2. 커널, 인터페이스 (0) | 2022.04.18 |