반응형
스레드에 대해 공부를 하다가 운영체제에 따라 구분되는 형태들에 대해 개념이 애매모호해서 확실히 머릿속에 새기고자 이 글을 작성하게 되었다.
스레드는 운영체제에 따라 다양하게 구현할 수 있는데, 대부분 다음 세 가지 형태로 구현한다.
- 사용자 수준 스레드(user-level thread) : 다대일(n : 1) 매핑
- 커널 수준 스레드(kernel-level thread) : 일대일(1 : 1) 매핑
- 혼합형 스레드(multiplexed thread) : 다대다(n : m) 매핑
1. 사용자 수준 스레드
- 스레드를 관리하는 라이브러리로 인해 사용자 단에서 생성 및 관리되는 스레드이다.
- 스레드 라이브러리는 커널이 지원하는 스케줄링이나 동기화 같은 기능을 대신 구현해준다.
- 그러므로 커널 입장에서는 이 스레드는 하나의 프로세스처럼 보이지만(커널이 따로 관리하지도 않고, 이 스레드에 대해 알지도 못함), 커널이 하는 일을 라이브러리가 대신 처리하여 여러 개의 스레드를 작동한다.
- 따라서, 사용자 프로세스 내에 여러 개의 스레드가 존재하지만 커널의 스레드 하나와 연결되기 때문에 “n : 1” 매핑이다.
- 라이브러리가 직접 스케줄링을 하고 작업에 필요한 정보를 처리하기 때문에 문맥 교환이 필요 없다.
단점
- 프로세스에 속한 사용자 스레드 중 입출력 작업 등에 의해 하나라도 block이 걸린다면 전체 사용자 스레드가 block 된다.
- 여러 개의 사용자 스레드가 하나의 커널 스레드와 연결되기 때문에 커널 스레드가 입출력 작업을 위해 대기 상태에 들어가게 되면 모든 사용자 스레드가 같이 대기하게 되는 것이다.
- 커널 입장에서는 하나의 단일 스레드 프로세스이므로 일부 스레드만 대기 상태로 보낼 수 없기 때문이다.
2. 커널 수준 스레드
- 커널 레벨에서 생성되는 스레드이며, 운영체제 시스템 내에서 생성되어 동작하고, 커널이 직접 관리한다.
- 커널이 멀티 스레드를 지원하는 방식으로 하나의 사용자 스레드가 하나의 커널 스레드와 연결되기 때문에 “1 : 1” 매핑이다.
- 프로세스가 생성이 되면 커널은 제어하기 위한 커널 수준의 스레드를 1개 만들기 때문에 프로세스는 적어도 하나 이상의 커널 스레드를 가지고 있다. (의문점 1, 2 참고)
- 커널 스레드는 독립적으로 스케줄링이 되므로 특정 스레드가 대기 상태에 들어가도 다른 스레드는 작업을 계속할 수 있고, 또한 커널이 제공하는 보호 기능과 같은 모든 기능을 사용할 수도 있다.
단점
- 스케줄링과 동기화를 위해 매번 커널을 호출하기 때문에 무겁고 오래 걸린다.
- 즉, 사용자 모드에서 커널 모드로의 전환이 빈번하게 이루어져 성능 저하가 발생한다. (문맥 교환(Context Switching)으로 인한 오버헤드 부하가 많아진다.)
- 커널 입장에서는 하나의 단일 스레드 프로세스이므로 일부 스레드만 대기 상태로 보낼 수 없기 때문이다.
🤔 의문점 1 : 스레드는 프로세스 단위라면서 어떻게 운영체제 레벨인 커널 안이 아니라 커널 밖에서 생성하여 이용할 수 있는가? 스레드가 커널 밖에 있다?
💡 이것은 실제 물리적으로 정말 커널 밖에 있고 그런 것이 아니라, 전부 커널 내부에 있지만 커널의 통제권 안에 있는지의 차이인 것이다. 커널에는 ‘커널 모드’와 ‘사용자 모드’ 두 가지가 있고, 여기서 ‘사용자 모드’에서 동작하는 스레드가 사용자 수준 스레드인 것이다. 입출력 인터럽트가 발생하면 커널은 ‘사용자 모드’가 되어서 사용자 수준 스레드의 응답을 기다린다. 사용자 수준 스레드의 응답이 오면 다시 ‘커널 모드’로 변환되어 이어서 커널 스레드가 일 처리를 하게 되는 것이다.
위 사진을 봐보자. 위 사진은 사용자 수준 스레드와 커널 수준 스레드가 1 : 1로 매핑되어 있고, 이를 커널 수준 스레드 모델이라고 부른다. (근데 왜?)
🤔 의문점 2 : 사용자 수준 스레드도 있는데 왜 이 형태가 커널 수준 스레드 모델인 것인가?
💡 위 방식이 기본적으로 프로세스가 생성되면 나타나는 형태이기 때문이다. 하나의 프로세스는 기본적으로 하나 이상의 스레드를 가진다. 그리고 사용자 레벨 부분과 동기화를 할 수 있도록 사용자 레벨 쪽에도 작은 스레드가 생성되는 것이다.
하지만 오해하지 말아야 하는 게, 저 사용자 레벨의 스레드는 커널이 관리하는 스레드가 아니다. 해당 프로세스에 대한 사용자의 입출력을 받을 수 있도록 하는 커널 통제권 밖의 작은 스레드일 뿐이다. 그러니 사용자 입출력이 필요로 한 프로세스는 실제로는 두 개 이상의 스레드를 가지게 되는 것이다.
결론은, 커널 스레드에 사용자 수준 스레드가 각 하나씩 붙어서 일 처리를 하는 저 형태가 커널 수준의 스레드 모델인 것이다.
🧐 더 깊게 : 사용자 수준 스레드
💡 위 사진처럼, 사용자 수준 스레드는 하나의 커널에 여러 스레드가 붙는다.
이것은 사용자 레벨에서 스레드 라이브러리를 이용해서 여러 스레드를 사용한 것이다. 개발자가 자바에서 스레드 함수를 이용하면 이와 같이 된다. 여기의 스레드는 운영체제 단의 기능을 하는 것이 아니라, 개발자가 기능 구현할 때 현재 기능 내에서 일 처리를 하는 스레드를 만들 듯이, 프로세스 내 커널과 관련 없는 기능들만 수행하는 스레드이다. 그래서 커널이랑 관련도 없고 커널은 이런 스레드들이 있는지도 모른다.
그렇기에 사용자 수준 스레드는 컨텍스트 스위칭이 없는 것이고, 스레드 교체 등으로 인한 오버헤드 발생이 없는 것이다.
3. 혼합형 스레드
- 사용자 스레드와 커널 스레드를 혼합한 방식으로 “n : m” 매핑이다.
- 혼합형 스레드에서는 커널 스레드의 개수가 사용자 스레드 개수보다 같거나 적어야 한다.
- 혼합형 스레드는 사용자 스레드와 커널 스레드의 방식을 혼용하기 때문에 사용자 스레드와 커널 스레드의 장단점을 모두 가지고 있는데 하나의 커널 스레드가 대기 상태에 들어가게 되면 다른 커널 스레드가 대신 작업을 하여 사용자 스레드보다 유연하게 작업을 처리할 수 있다.
- 다만, 커널 스레드를 같이 사용하기 때문에 여전히 문맥 교환 시 오버헤드가 있어 사용자 스레드만큼 빠르지 않다.
- 따라서, 빠르게 움직여야 하는 스레드는 사용자 스레드로 작동하고 안정적으로 움직여야 하는 스레드는 커널 스레드로 작동한다.
출처 / 참고 :
https://helloinyong.tistory.com/293