본문 바로가기

CS

커널 레벨 쓰레드와 유저 레벨 쓰레드

먼저 간단하게 스레드의 개념과 커널 레벨 스레드, 유저 레벨 스레드를 살피고 가자

 

스레드(thread)는 어떠한 프로그램 내에서, 특히 프로세스 내에서 실행되는 흐름의 단위를 말한다. 일반적으로 한 프로그램은 하나의 스레드를 가지고 있지만, 프로그램 환경에 따라 둘 이상의 스레드를 동시에 실행할 수 있다. 이러한 실행 방식을 멀티스레드(multithread)라고 한다.

사용자 레벨 스레드 (User-Level Thread)

사용자 스레드는 커널 영역의 상위에서 지원되며 일반적으로 사용자 레벨의 라이브러리를 통해 구현되며, 라이브러리는 스레드의 생성 및 스케줄링 등에 관한 관리 기능을 제공한다. 동일한 메모리 영역에서 스레드가 생성 및 관리되므로 속도가 빠른 장점이 있는 반면, 여러 개의 사용자 스레드 중 하나의 스레드가 시스템 호출 등으로 중단되면 나머지 모든 스레드 역시 중단되는 단점이 있다. 이는 커널이 프로세스 내부의 스레드를 인식하지 못하며 해당 프로세스를 대기 상태로 전환시키기 때문이다.

커널 레벨 스레드 (Kernel-Level Thread)

커널 스레드는 운영체제가 지원하는 스레드 기능으로 구현되며, 커널이 스레드의 생성 및 스케줄링 등을 관리한다. 스레드가 시스템 호출 등으로 중단되더라도, 커널은 프로세스 내의 다른 스레드를 중단시키지 않고 계속 실행시켜준다. 멀티프로세싱 환경에서 커널은 여러 개의 스레드를 각각 다른 프로세서에 할당할 수 있다. 다만, 사용자 스레드에 비해 생성 및 관리하는 것이 느리다.

many-to-one model 은  요즘 잘 안쓰인다고한다  최근 운영체제들은 one-to-one model을 사용

유저 쓰레드 특징

  • 프로세스 1개(사용자 스레드 N개) 당 커널 스레드 1개가 할당된다.
  • 프로세스 내에 스레드 라이브러리가 있어서 커널의 도움 없이 스레드의 스케줄링을 할 수 있다.
  • 스레드 정보(TCB, Thead Control Block)는 프로세스 내에서, 프로세스 정보(PCB, Process Control Block)는 커널에서 관리한다.

장단점으로는

  • 스케줄링과 동기화를 위해 System Call(커널 호출) 하지 않기 때문에 오버헤드 적음.(Context Switching을 프로세스 내부에서 진행하면 됨)
  • 커널이 스레드 존재를 모르기 때문에 유저모드와 커널 모드 간 전환이 없다. 프로세스 하나로 봄
  • 스케줄링 우선순위를 지원하지 않으므로 어떤 스레드가 먼저 동작할지 모름, 다만 위에서 말한 라이브러리 통해서 스케줄링함
  • 하나의 스레드가 System Call(커널 호출)하면 해당 프로세스 내 모든 스레드가 중단됨(Blocking System Call)

커널 쓰레드 특징

  • 프로세스 내의 사용자 스레드 1개 당 커널 스레드 1개가 할당된다. (사용자 스레드를 생성하면 할당할 커널 스레드를 1개 생성한다.)
  • 프로세스 내에 스레드 라이브러리가 없어서 커널 스레드를 스케줄 하여 매핑된 사용자 스레드를 동작시킨다.
  • 커널이 전체 TCB와 PCB를 관리한다.

장단점

  • 커널이 각 스레드 개별적으로 관리할 수 있음
  • 동작중인 스레드가 System Call(커널 호출) 해도 해당 프로세스 내 다른 스레드가 계속 실행될 수 있음.
  • 스케쥴링과 동기화를 위해 System Call(커널 호출)하는데 오래 걸림
  • 유저 모드와 커널 모드 간 전환이 빈번하여 성능 저하

혼합된 스레드 모델 특징

  • User-level threads와 Kernel-level threads를 섞은 방법입니다. User-level thread(줄여서 Thread)는 LWP(가벼워진 프로세스, Lightweight Processes)에 의해 multiplex 됩니다. 커널은 LWP를 스케줄링/실행하고, LWP는 대기 중인 thread를 골라서 실행합니다. (커널과 프로세스 간의 중간자 역할을 한다.)
  • thread는 하나의 LWP에서 실행이 되며, Time slice가 바뀔 때 LWP도 바뀌어질 수 있습니다. 프로그래머는 thread를 사용할 수도 있고, LWP를 직접 사용할 수 있고, 둘 모두를 동시에 사용할 수도 있습니다.
  • User-level threads처럼 작동하면서 Hardware Parallelism과 Blocking calls에 대처할 수 있으며, Context-Switch을 많이 하지 않습니다.
  • 이것의 장애는, LWP가 Blocking이 되면 이 LWP가 가진 몇 개의 Thread도 동시에 Blocking이 됩니다. 또한 LWP의 Context-Switch 비용은 Kernel-level threas보다 결코 싸지 않습니다. 또한 다중 CPU에서 효율적일려면 각 Thread는 각각 다른 LWP에 할당되어 있어야 합니다.  각 Thread의 LWP 할당과 LWP의 CPU 할당은 별개로서 이루어지기 때문에, 각 Thread가 서로 다른 CPU에 할당되려면 이렇게 작동하게끔 하는 메커니즘이 따로 존재하여야 합니다.

이러한 이유로 인해 LWP에 의한 multiplexed threads는 궁극의 해결책은 못됩니다. 이상적으로, Kernel-level threads의 결정적인 단점인 Thread Context-Switch를 user-level threds만큼 빠르게만 한다면 그것으로서 모든 장애는 해결됩니다. 물론 이 방법은 있지만 여전히 문제점을 가지고 있습니다. 아래 방법입니다.

Scheduler Activation(kernel-supported user-level threads)

이 방법은 User-level threads들을 위한 특별한 지원을 kernel이 해주는 겁니다. Scheduler Activation이라 합니다. User-level threads 라이브러리는 커널에게 프로세스를 요구할 때와 양도할 때를 알려줍니다. 그러면 커널의 Scheduler Activation은 이것을 커널에 의한 프로세스 주소 공간으로 할당된 Virtual Processor로 표현합니다. 여기서 스케줄링과 Blocking 감지가 이루어지며, Granted processor, Preemptive thread, Blocked, Unblocked 등등의 Event를 User-level의 런타임 시스템에게 알려줍니다.

그러나 위의 방식도 단점이 있는데 커널과 라이브러리 코드가 교신을 위해 주소 공간을 공유하기 때문에 높은 신뢰가 있어야 한다. 이 방법은 버그 등에 robust 하지 않습니다.

참고:

'CS' 카테고리의 다른 글

Pintos project 1 Alarm clock, priority scheduling  (0) 2021.10.04
CPU 가상화  (0) 2021.10.04
프로시저  (0) 2021.10.02
전통적 동기화 문제와 데드락  (0) 2021.09.26
동시성 이슈  (0) 2021.09.25