1. 쓰레드 개요
1. 쓰레드가 나오게 된 계기
쓰레드가 나오게 된 계기는 프로세스의 문제점에 있다. 일단 전 게시물에 프로세스 생성 과정은 상당히 복잡하다고 했다.
메모리를 할당한 뒤 메모리를 fork()해주고 PCB를 할당한 다음에 준비 상태 -> 실행 상태 -> exec() 등등 상당히 복잡한 과정을 거치므로 생성의 오버헤드가 큰 편이다.
또한, 한 프로세스에서 다른 프로세스로 옮겨가는 과정인 Context Switching 과정도 오버헤드가 크다. 우선 기존에 처리하던 프로세스의 정보들을 다 저장을 한 뒤 새로운 프로세스를 실행한 뒤 다시 복귀하는 과정에서도 그 과정을 한 번 더 반복해야 한다.
마지막으로, 프로세스 간의 통신이 어렵다. 프로세스는 완전히 독립된 주소 공간을 가지고 있기에 개입이 힘들다.
이러한 이유로 쓰레드가 등장하게 된 것이다.
프로세스는 더 '작은 실행단위'로써 현대 운영체제가 작업을 '스케쥴링' 하는 단위이다.
2. 프로세스는 쓰레드들의 컨테이너이다.
쓰레드는 곧 함수이다! 프로세스는 반드시 한 개 이상의 쓰레드로 구성되어있다.
프로세스가 생성될 때 운영체제에 의해 자동으로 1개의 쓰레드가 생성된다. 이를 main 쓰레드라 한다.
또한, 하나의 컨테이너가 여러 개의 쓰레드를 가질 수도 있다. 이를 멀티 쓰레드라고 한다.
프로세스는 쓰레드들의 공유 공간을 제공해준다. 모든 쓰레드는 프로세스의 코드, 데이터, 힙을 공유한다.
-> 여기서 프로세스 간의 통신이 용이해진다. (단, 스택은 쓰레드 별로 별도의 공간을 사용한다.)
마지막으로, 쓰레드의 생명은 프로세스 생명과도 같다. 쓰레드로 만든 함수가 종료되면 쓰레드가 종료된다. 또한, 프로세스의 모든 쓰레드가 종료될 때는 프로세스도 같이 종료된다. 만약? 프로세스가 같이 종료된다? 그러면 쓰레드는 자동으로 종료가 된다.
◆ 프로세스와 쓰레드 요약
1) 프로세스
프로세스는 통신이 어렵고 실행하는데 상당히 오버헤드가 크다. 하지만, 프로세스는 독립적인 개체로 독립적인 업무 수행이 가능하다. (은행과 은행 창구에서 은행과 같은 역할이랄까?)
2) 쓰레드
쓰레드는 통신에 용이하고 실행하는데 오버헤드도 작다. 하지만, 쓰레드는 프로세스에 종속적이므로 쓰레드 혼자 업무 수행을 할 수 없다.
프로그램의 실행 단위가 함수이기에 쓰레드 단위도 함수이다. 또한, 실행 순서를 알 수 없다는게 쓰레드의 특징이다.
3. 쓰레드의 장단점
1. 장점
-CPU 응답성이 향상된다.
- 자원을 공유함으로써 효율성이 향상된다.
2. 단점
- 모든 자원을 공유하면, 하나의 쓰레드가 어긋날 때 프로세스가 다 죽을 수 있다.
- 또한, Context Switching이 용이할지라도 너무 많아지면 성능 상 문제가 생길 수 있다.
2. 쓰레드 Deep Dive
1. 쓰레드 주소 공간
- 쓰레드가 생성되고 실행되는 동안 접근 가능한 메모리 영역
- 쓰레드 주소 공간은 프로세스의 주소 공간 내에 형성
i) 쓰레드 사적 공간
: 쓰레드 코드, 쓰레드 로컬 스토리지, 쓰레드 스택
ii) 쓰레드 사이의 공유 공간
: 프로세스의 코드, 프로세스 데이터 공간, 프로세스 힙 영역 (= 코드, 데이터, 힙 영역은 공유한다는 것이네)
2. 쓰레드 라이프 사이클
- 프로세스 라이프 사이클과 거의 흡사 -> TCB로 관리한다.

1) 쓰레드 생성 : 쓰레드를 생성하는 syscall 혹은 라이브러리 함수를 호출하여 다른 쓰레드 생성이 가능하다. 자동으로 main 쓰레드가 생성된다.
2) 쓰레드 종료 : 프로세스 종료와 쓰레드 종료 구분 필요
- 프로세스 종료 : 프로세스에 속한 어떤 쓰레드라도 exit() syscall을 부르면 프로세스가 종료된다. 또한, 메인 쓰레드가 종료되면 모든 쓰레드도 함께 종료된다. 자동으로 프로세스도 종료된다.
- 쓰레드 종료 : pthread_exit()와 같은 함수로 해당 쓰레드만 종료한다. main() 함수에서 pthread_exit()함수를 부르면 역시 main 쓰레드만 종료
3) 쓰레드 조인 : 쓰레드가 다른 쓰레드가 종료할 때까지 대기한다. 보통 부모 자식 관계 쓰레드에서 이뤄진다.
4) 쓰레드 양보 : 자발적으로 yield() 함수 호출을 하면 자신의 실행을 중단하고 다른 쓰레드를 스케줄하도록 지시한다.
3. Thread Context Switching
- 쓰레드의 실행 중인 상태 정보들은 TCB에 저장된다.
- Thread Context Switching의 과정 : CPU 레지스터 저장 및 복귀 → 커널 정보 수정
3. 쓰레드 모델
1. Kernel - Level Thread
▶ 커널 쓰레드 : 커널이 직접 생성하고 관리하는 쓰레드
- 응용 프로그램이 시스템 호출을 통해 커널 레벨 쓰레드 생성
- 커널이 쓰레드에 대한 정보를 커널 공간에 생성하고 소유
- 쓰레드 주소 공간 : 사용자 공간에 존재
- main 쓰레드는 커널 쓰레드
▶ 순수 커널 레벨 쓰레드
- 부팅 때부터 커널의 기능을 돕기 위해 만들어진 쓰레드이다.
- 쓰레드의 주소 공간은 모두 커널 공간에 형성된다. (커널 쓰레드랑 다르다)
2. User - Level Thread
▶ 사용자 쓰레드 : 라이브러리에 의해 구현된 일반적인 쓰레드
- 응용 프로그램이 라이브러리 함수를 호출하여 사용자 레벨 쓰레드 형성
- 쓰레드 라이브러리가 쓰레드 정보를 사용자 공간에 생성하고 소유
- 커널은 사용자 레벨의 쓰레드의 존재에 대해 알 수 없음 -> 하나의 프로세스로만 인식
- 쓰레드 주소 공간 : 사용자 공간에 존재
3. Multithreading models
- 구현 : 사용자가 만든 쓰레드가 시스템에서 스케줄되고 실행되도록 구현되는 방법
- 종류 : M:1, 1:1. M:N 모델 (사용자 레벨 쓰레드 : 커널 쓰레드)
4. 멀티쓰레드에서의 fork()와 exec()
- 멀티쓰레드에서 fork() 시스템 콜을 실행한다면?
→ 새로운 프로세스는 fork()를 호출한 쓰레드만 복제
- 한 쓰레드가 exec()를 호출할 시 프로세스 전체가 사라진다.
5. 자원 동기화 문제 : thread-safe 개념
하나의 자원에 대해 여러 쓰레드가 접근할 시 공유 데이터 훼손의 문제가 있다. 따라서, thread-safe를 지켜야하는데 방법은 다음과 같다.
1) Re-entrancy
: 어떤 함수가 한 쓰레드에 의해 호출되어 실행중일 때, 다른 쓰레드가 그 함수를 호출하더라도 결과가 각각에게 올바르게 주어져야 한다.
2) Thread-local stroage
: 동기화 방법과 관련되어 있으며 공유 자원의 사용을 최소로 줄인다.
3) Mutual Extension
: 공유 자원을 꼭 사용해야 할 경우 접근 할 때 락으로 통제한다.
4) Atomic Operations
: 공유 자원을 이용할 때 원자 연산을 이용하거나, '원자적'으로 정의된 접근 방법을 사용한다.
끝!
'CS 전공 > OS' 카테고리의 다른 글
[운영체제] 7. 프로세스와 쓰레드의 동기화 (Synchronization) (0) | 2024.06.23 |
---|---|
[운영체제] 6. 스케줄링 (2) | 2024.04.21 |
[운영체제] 4. 프로세스 (2) (2) | 2024.04.18 |
[운영체제] 3. 프로세스 (1) (0) | 2024.04.18 |
[운영체제] 2. 컴퓨터 아키텍쳐와 운영체제 (0) | 2024.04.16 |