운영체제 강의노트 정리 - 스레드

스레드

개요

스레드thread는 프로세스와 마찬가지로 CPU의 작업 단위이나, 경량 프로세스lightweight process라고 불린다.

스레드는 자원의 관리보다는, 프로그램의 하나의 실행 흐름으로서 CPU에서 실행되기 위해 스케줄되어야 하는 개체이다.

(프로세스는 프로그램 수행과 그것에 필요한 자원을 하나의 개체에서 관리하기 위한 방법이다.)

스레드는 스레드 식별자 / 프로그램 카운터 / 레지스터 집합 / 스택을 별도로 가지며, 텍스트 / 데이터 섹션, 다른 운영체제 자원 등은 같은 프로세스에 속한 다른 스레드와 공유한다.

하나의 프로세스에서 병행 수행되는 스레드는 같은 주소 공간과 자원을 공유하며, 하나의 컴퓨터에서 병행 수행되는 프로세스는 같은 물리 메모리와 디스크를 공유한다.

다중 스레드를 사용하는 것이 무조건적인 성능 향상을 의미하는 것은 아니다.

동기

다중 스레드를 활용하면 한 응용 프로그램에서 여러 가지 일을 동시에 수행할 수 있다.

물론 자식 프로세스를 생성하여 이를 처리할 수 있으나, 프로세스 생성은 비용이 크며, 자원 공유도 쉽지 않다.

유닉스의 경우 스레드 생성 비용은 프로세스 생성 비용보다 10배 정도 빠르다.

스레드의 특성

스레드도 프로세스와 마찬가지로 같은 상태 변화를 한다.

프로세스는 부모 프로세스와 자식 프로세스를 구분하지만, 같은 프로세스 내에 있는 스레드는 보통 이러한 구분을 하지 않는다.

장점

  • 응답성responsiveness : 다중 스레드 프로그램은 일부가 블록되어도 나머지 부분은 계속 실행될 수 있다.
  • 자원 공유resource sharing : 같은 프로세스의 스레드는 메모리와 그 밖의 프로세스 자원을 공유한다. 때문에 스레드 간 통신이 용이하다.
  • 경제성economy : 프로세스마다 자원과 메모리를 할당하면 많은 오버헤드가 발생하는데, 스레드를 사용하여 생성 비용을 저렴하게 하고 스레드 간 문맥 전환을 용이하게 한다.

사용자 및 커널 스레드

스레드는 사용자 공간에 구현되거나, 커널 공간에 구현되거나, 혼합되어 구현될 수 있다.

사용자 스레드user thread

스레드 라이브러리를 통해 제공되며, 커널의 지원 없이 스레드의 생성, 스케줄링, 관리를 제공한다. 때문에 모드 변경이 필요 없어 스레드의 생성과 관리를 빠르게 할 수 있다.

프로세스마다 자체적 스케줄링 알고리즘을 가질 수 있으나, 커널은 스레드 단위로 시분할 하지 않는다.

커널이 단일 스레드일 때, 프로세스의 하나의 스레드가 블록되면 전체 프로세스가 블록된다.

다중 프로세서의 장점을 이용할 수 없다.

POSIX의 Pthread 등이 해당된다.

커널 스레드kernel thread

운영체제가 직접 지원하며, 커널이 스레드의 생성, 스케줄링, 관리를 담당한다.

모드 변경이 필요하므로 스레드 생성 및 관리가 사용자 스레드보다 느리다.

하나의 스레드가 블록되어도 같은 프로세스에 있는 다른 스레드를 계속 실행할 수 있다.

다중 스레드 모델

일반적으로 운영체제는 사용자 스레드와 커널 스레드를 모두 제공한다.

커널은 커널 스레드의 존재만 인식하며, 커널은 커널 스레드를 스케줄링하여 실행한다.

다대일 모델

여러 사용자 스레드 <-> 하나의 커널 스레드

스레드 관리가 사용자 모드에서 이루어져 처리가 빠르나, 하나의 스레드가 블록되면 전체 프로세스가 블록되며, 다중 프로세스에서 다중 스레드가 동시에 수행될 수 없다.

일대일 모델

하나의 사용자 스레드 <-> 하나의 커널 스레드

하나의 스레드가 블록되어도 나머지 스레드는 계속 실행될 수 있고, 다중 프로세스에서 동시에 수행될 수 있으나, 비용이 비싸다.

다대다 모델

여러 사용자 스레드 <-> 여러 커널 스레드

비용이 일대일 모델모다 저저렴하며, 스레드의 동시 수행도 가능하다.

스레드 쟁점

fork 및 exec 시스템 호출

유닉스는 두 종류의 fork 시스템 호출을 제공한다.

  • 스레드가 fork 시스템 호출을 하면 프로세스의 모든 스레드가 복사된다.
  • 스레드가 fork 시스템 호출을 하면 호출한 스레드만 복사된다.

스레드가 exec 시스템 호출을 하면 전체 프로세스가 새로운 프로그램으로 교체된다.

취소

스레드 취소thread cancellation은 실행 중인 스레드를 강제로 종료하는 것을 말한다.

스레드 취소는 두 가지 형태를 갖는다.

  • 비동기식 취소 : 목표 스레드가 바로 종료된다.
    • 스레드에게 할당된 자원이 모두 자동으로 해제되지 않을 수 있다.
  • 지연된 취소 : 목표 스레드는 주기적으로 자신이 종료되어야 하는지 검사하고 적절한 시기에 종료된다.

신호 처리

유닉스에서는 신호signal를 이용하여 특정 사건이 일어났음을 프로세스에 통보한다. 신호는 소프트웨어 인터럽트다.

동기식 신호는 자신에 의해 생성된 신호를 말하며, 그것을 생성한 프로세스에게 전달된다. (예. 잘못된 메모리 접근)

비동기식 신호는 외부에 의해 생성된 신호를 말하며, 그 생성은 예측될 수 없다. (예. ctrl+c)

특정 사건의 발생에 의해 신호가 발생하면, 그 신호는 프로세스에게 전달되고, 프로세스는 신호를 처리한다.

모든 신호마다 그것을 처리하는 기본 신호 처리기가 있으며, 이는 커널이 수행한다.

사용자가 신호 처리기를 커스터마이징하면, 기본 신호 처리기 대신 이 처리기가 신호를 처리한다.

스레드에서 신호를 처리하는 방법은 다음과 같다.

  • 신호에 해당하는 스레드에게만 전달 (동기식 신호 처리에 적합)
  • 프로세스의 모든 스레드에 전달 (비동기식 신호 처리에 적합)
  • 프로세스의 일부 스레드에게만 전달
  • 프로세스의 모든 신호를 처리하는 특정 스레드를 두어 처리

유닉스에서는 스레드가 수신할 신호와 무시할 신호를 지정할 수 있다.

스레드 풀

프로세스가 생성할 수 있는 스레드의 수를 적절하게 관리하기 위해 사용되는 메커니즘.

프로세스가 시작될 때 적정 수의 스레드를 생성하여 스레드 풀에 대기하도록 하며, 스레드가 필요할 때 풀에 있는 스레드를 활성화하여 사용하고, 실행이 끝나면 다시 스레드 풀로 들어가 대기한다.

스레드 풀을 이용하여 작업을 빠르게 처리할 수 있으며, 스레드 수를 효과적으로 제한할 수 있다.

스레드 전용 데이터

스레드는 보통 같은 프로세스에 속한 스레드와 데이터를 공유하며, 스레드 라이브러리가 지원하는 스레드 전용 데이터thread-specific data를 사용할 수 있다.