풀스택 웹🌐 개발자 지망생 🧑🏽‍💻
➕ 인공지능 관심 🤖


Categories


Recent views

  • 1
  • 2
  • 3
  • 4
  • 5

OS 정리-Chap 3-프로세스와 스레드

3. 프로세스와 스레드

🗣️ 출처

IT COOK BOOK 운영체제 (개정 3판, 구현회 저, 한빛 아카데미) 를 정리한 내용입니다.

프로세스의 개념과 상태 변화

프로세스(process)란?

프로세스(process) 또는 작업(task)는 다음과 같이 여러 의미로 정의 된다.

  • 주소 공간을 가지고 실행 중인 프로그램

  • 비동기적 행위

  • 실행중인 프로시저 또는 이의 제어 추적

  • 운영체제에 들어 있는 프로세스 제어 블록(PCB)

  • 프로세서에 할당하여 실행할 수 있는 개체 디스패치가 가능한 대상

프로그램은 컴파일한 코드, 초기화 전역변수, 문자열, 상수 등의 정적 데이터를 포함한 정적인 개체이다.

프로그램이 동적인 개체인 프로세스가 되려면, 자신만의 메모리 영역을 할당받아야 하며, 프로그램 인스턴스 갯수에 따라 프로세스의 갯수도 달라진다.
즉, 같은 프로그램이라도 2개를 실행하면 각기 다른 프로세스이다.

프로세스는 프로세서 점유 시간, 메모리, 파일 ,입출력 장치 같은 자원을 스케줄러로부터 할당받아야 하며, 자신의 메모리 영역에는 나중에 배울 프로세스 제어 블록 (PCB)에 자신의 정보를 저장한다.
스케줄러는 추가로, 프로세스의 교착 상태, 보호, 동기화 지원 및 실행 순서를 결정하는 역할도 한다.

프로세스를 통해서 병행 실행 프로그램들의 자원 공유를 효율적으로 구현할 수 있게 되었다.

프로세스 메모리 구조

이때 프로세스는 아래와 같은 그림 3-2와 같은 모습으로 메모리에 적재된다.

메모리 구조는 다음과 같이 4개로 구분된다.

  • 스택(stack)

    스택은 데이터를 일시적으로 저장하는 영역으로, 지역변수, 호출한 함수의 반환 주소, 반환 값, 매개 변수등에 사용된다. 서브루틴(함수)을 호출할수록 스택 포인터로 지시되고 있는 스택 영역의 크기가 커지고, 함수가 반환되면 줄어든다.

  • 힙(heap)

    힙은 코드 영역과 별도로 유지되는 자유 영역으로, 시스템 호출을 통한 동적 메모리 할당 시에 사용되며, 스택 영역과 마찬가지로 힙 포인터로 힙 영역의 크기를 알 수 있다.

    스택 영역과는 정 반대 방향으로 메모리가 증가하는데, 이때 빈 공간이던 스택 포인터와 힙 포인터 사이가 좁혀져 서로 만나면, 메모리가 소진되었다고 판단한다.

  • 데이터(data)

    데이터 영역은 프로그램의 가상 주소 공간으로, 전역, 정적 변수를 저장 및 할당하고, 실행전 초기화한다. 실제로는 읽기 전용 뿐만 아니라 읽기 및 쓰기 영역으로 사용할 수 있으며, 정적변수는 0으로 초기화할 수 있으며, 초기화 하지 않으면 데이터 영역의 끝에서 시작한다.

    DB, 문서 편집기처럼 같은 프로그램을 실행하는 여러 프로세스들이 이 부분을 공유하도록 프로그래밍할 수 있는데, 이러한 프로그램을 재진입 프로그램이라고 한다.

  • 코드(code)

    코드 영역은 실행 명령, 목적 파일이 존재하는 메모리 영역으로, 즉 디스크에서 읽어 실행을 위해 컴파일된 프로그램 코드가 적재된다. 변경이 불가능하므로, 이 곳에 쓰기를 시도하면 오류가 난다. 여러 프로세스가 공유할 수 있으므로, 같은 프로그램을 여러 창 띄울 경우 모두 공유한다.

프로세스 상태 변호와 상태 정보

운영체제는 작업 스케줄러, 프로세서 스케줄러를 통해 프로세스의 상태를 점검 및 제어하여 자원을 효율적으로 사용하게 만든다.

프로세스 상태 변화

프로세스 스케줄러는 그림 3-5와 같이 프로세스의 상태를 변화시킨다. 각 상태의 설명과 상태변화를 주시하자.

추가적으로 위와 같이 생성 상태는, 잡 스케줄러가 디스크에 저장한작업 중 실행할 작업을 선정(Spooling)하여 준비리스트에 삽입한 상태를 의미한다. 잡 스케줄러는 이러한 접수된 프로세스를 준비큐에 넣어 준비상태가 되며, 디스패처에 의해 실행 상태로 바꾼다.

상태 변화 표기 방법 상세
준비 $\rightarrow$실행 dispatch(프로세스명) 준비 큐 맨 앞의 프로세스가 프로세서를 점유하는 것을 dispatch라고 하며, 할당 시간이 주어져 프로세서 독점을 방지한다.
실행 $\rightarrow$준비 timeout(프로세스명) 자발적으로, 혹은 인터럽트 클록을 통해 할당된 시간이 넘어가면 프로세서가 반환되며, 준비 상태로 돌아간다.
준비 $\rightarrow$대기(보류) block(프로세스명) 할당 시간 종료 이전에 입출력 연산 등이 필요해지면 새로운 자원 요청 등의 문제로 프로세서를 스스로 양도하고 대기 상태가 된다.
대기(보류) $\rightarrow$준비 wakeup(프로세스명) 입출력 작업이 끝나면 wakeup으로 대기에서 준비상태가 된다.

프로세스 제어 블록(PCB, Process Control Block)

프로세스 제어 블록(PCB, Process Control Block) 혹은 작업 제어 블록(TCB, Task Control Block)은 특정 프로세스 정보를 저장하는 데이터 블록이나 레코드를 의미하며, 프로세스의 생성과 삭제를 함께한다.
아래와 같은 항목의 정보를 가지고 있으며, 운영체제의 모든 모듈이 읽고 수정 가능하다.

블록명 상세
프로세스 식별자 각 프로세스의 고유 식별자(숫자, 색인 항목)
프로세스 상태 생성, 준비, 실행, 대기, 중단 등 상태 표시
프로그램 카운터 프로세스를 실행하는 다음 명령의 주소 표시
레지스터 저장 영역 누산기, 인덱스 레지스터, 스택 포인터, 범용 레지스터, 조건 코드 등 정보로, 컴퓨터 구조에 따라 수나 형태가 다르다. 인터럽트가 발생하면 프로그램 카운터와 함께 저장하여 재실행할 때 원래대로 복귀할 수 있게 한다.
프로세서 스케줄링 정보 프로세스의 우선순위, 스케줄링 큐의 포인터, 기타 스케줄 매개변수
계정 정보 프로세서 사용 시간, 실제 사용시간, 사용 상한 시간, 계정 번호, 작업이나 프로세스 번호 등
입출력 상태 정보 특별한 입출력 요구 프로세스에 할당된 입출력장치, 열린 파일 리스트 등
메모리 관리 정보 운영체제가 사용하는 메모리 시스템에 따른 경계 레지스터, 페이지 테이블이나 세그먼트 테이블 값 등
기타 등등

프로세스의 관리

프로세스의 계층 구조

프로세스는 실행 중 프로세스 생성 시스템을 호출하여 계층 구조의 새로운 프로세스를 만들 수 있는데, 생성 순서에 따라 부모-자식 관계를 유지하여 그림 3-9와 같이 계층적으로 생성할 수 있다.

이때, 프로세스를 생성하는 프로세스가 부모 프로세스이고, 생성되는 프로세스가 자식 프로세스이다.

이러한 계층 구조는 다음과 같은 기능을 위해 사용된다.

자식 프로세스로의 자원 분배

자식 프로세스는 프로세서, 메모리 같은 필요한 자원을 직접 운영체제로부터 얻어내거나, 부모 프로세스로 부터 일부 얻어낼 수 있다.
또한 부모 프로세스는 자식 프로세스가 가져갈 수 있는 자원량을 제한할 수도 있다.

자식 프로세스로의 데이터 분배

초기화 시, 일부 데이터를 자식프로세스에게 줄 수 있다. 예를 들어 자식 프로세스가 파일 이름을 화면에 출력하는 일을 한다면, 생성 시, 부모 프로세스로 부터 파일 이름을 받아올 수 있다.

자식 프로세스의 종료

부모 프로세스만이 자식 프로세스를 종료시킬 수 있으며, 다음과 같은 경우 자식 프로세스가 종료된다.

  1. 부모 프로세스가 종료되면 자식 프로세스도 연속 종료 된다.

  2. 자식 프로세스가 자신에게 할당된 모든 작업을 끝낸다.

  3. 부모 프로세스가 자식 프로세스를 명시적으로 종료한다.

  4. 자식 프로세스가 할당된 자원을 초과하여 자원을 사용했다.

자식프로세스와의 작업 순서 선택

생성된 자식 프로세스와 부모 프로세스의 작업 순서는

  1. 동시에 실행되거나,

  2. 자식 프로세스 작업을 끝낸 뒤, 부모 프로세스를 실행하는

선택지가 있다. 만약 부모 프로세스를 먼저 실행하고 싶다면, 자식 프로세스를 생성하기 전에 작업을 끝내고 생성하면 된다.

프로세스의 생애주기

프로세스의 생성

프로세스는 PCB 생성 뒤, 주소 공간이 할당되면 생성된다. 구체적으로 다음과 같다.

  1. 새로운 프로세스에 프로세스 식별자 할당

  2. 프로세스의 모든 구성 요소를 포함할 수 있는 주소 공간과 프로세스 제어 블록 공간을 할당

  3. 프로세스 제어 블록 정보(프로세스 상태, PC, 우선순위, 자원 요청 등) 초기화

  4. 링크 걸기(준비 큐에 삽입)

note

UNIX 계열 운영체제에서는 fork 명령어를 이용해 프로세스를 생성할 수 있으며, 기본적으로 부모 프로세스와 똑같이 복제되지만, exec 명령어로 자식 프로세스 공간을 덮어쓰는 것으로 새로운 자식 프로세스 또한 생성 가능하다.

추가로, 일괄 처리 환경에서는 준비 큐에 작업이 도착하면 프로세스를 생성하고, 대화형 환경에서는 새로운 사용자가 로그온할 때 프로세스를 생성한다.

프로세스의 종료

프로세스가 마지막 명령을 실행하면 종료하여 운영체제에 프로세스 삭제를 요청한다. 이외에도 프로세스가 종료되는 이유는 여러가지가 있으며 몇가지 예를 들자면, 앞선 정상적인 종료 요청, 할당 시간 초과, 오류 및 실패, 메모리 부족, 엑세스 위반 등이 있다.

note

UNIX 계열 운영체제에서는 exit 명령어로 프로세스를 종료한다.

부모 프로세스는 wait 명령어를 자식 프로세스의 종료를 기다릴 수 있다. 자식 프로세스가 종료되면 부모 프로세스에게 종료된 자식 프로세스의 식별자가 돌려지게 된다.

추가로 abort 명령어로도 프로세스를 종료할 수 있다. 부모 프로세스만이 자식 프로세스를 종료시킬 수 있으므로, abort 를 자식 프로세스에 사용하면 부모 프로세스가 호출된다.

자식 프로세스는 종료될 때 자신의 식별자를 부모 프로세스에게 전달한다.

일괄 처리 환경에서는 작업 종료를 의미하는 신호 인터럽트가 발생되거나 시스템 호출로 중단 명령을 받으면 프로세스가 종료된다.
대화형 환경에서는 사용자가 로그오프하거나 터미널을 닫으면 프로세스를 종료한다. 오류는 어떠한 환경에서도 종료된다.

프로세스의 제거

프로세서의 제거는 상태 변화와 관련 없이 프로세스를 파괴하는 것이다. 사용하던 자원과 PCB가 차지하는 메모리는 반환되며, 시스템 리스트나 테이블에서 삭제된다.

물론, 디스크에서는 프로그램이 삭제되지 않으며, 부모프로세스가 제거되면 자동으로 자식 프로세스도 제거된다.

프로세스 중단과 재시작

다중 프로그래밍 환경에서는 입출력 동작이 연산 속도보다 느리기 때문에, 대부분의 시간을 유휴시간으로 기다리게 된다.

이 문제를 해결하기 위해 다중 프로그래밍 환경에서는 림 3-10처럼 프로세스 중단(일시정지) 상태를 추가하여 해결할 수 있다.

기존의 비슷한 상태인 프로세스 대기 상태는 자원이 할당받기를 기다리는 상태라면, 프로세스 중단 상태는 할당받은 자원을 기다리는 상태이며, 재시작 이벤트를 통해 이전 상태로 돌아가게 된다.

사용례

자원을 할당받길 기다리지 않아도 되므로, 재시작 이벤트를 감지하는 즉시 실행 상태로 되돌아 갈 수 있어서 시스템 부하 조절에 용이하다.

뿐만 아니라, 장애 발생에 따른 기능 회복 대기, 프로세스 검사, 너무 많은 프로세스 적재 등에 사용된다.

예를 들어 프로세스가 더 많은 저장장치를 요구하는데 현재 사용가능한 저장장치가 부족하면 대기 상태가 되며, 시간이 지나 자원들이 사용가능하게 되면 대기상태로 바뀐다. 하지만 만약 영원히 자원을 얻을 수 없게 되면, 교착 상태가 되게 된다.

중단 상태

다중 처리 시스템에서는 다른 프로세서가 실행 중인 프로세스를 중단할 수 있고, 단일 처리 시스템에서는 해당 프로세스 스스로 중단해야 한다.

중단된 대기 상태는 프로세스가 보조 메모리에 있고 이벤트를 대기 중인 상태이며, 중단된 준비 상태는 프로세스가 보조 메모리에 있지만 즉시 메인 메모리로 적재하여 실행할 수 있는 상태이다.

중단한 프로세스는 원래 상태로 돌아가면 중단된 시점부터 다시 시작한다.

프로세스 우선순위 변경

프로세스 스케줄러는 PCB의 우선순위를 이용해 준비 리스트의 프로세스를 처리한다.

프로세서는 프로세서 중심 프로세스와 입출력 중심 프로세스로 구분할 수 있다.

같은 입출력 중심 프로세스 또한, 추가로 속도가 느리면서 빠른 응답을 요구하는 단말기 입출력 프로세스에 높은 우선순위를 부여하고, 속도가 빠른 디스크 입출력 프로세스에는 낮은 우선순위를 부여한다.

보통 우선순위가 낮은면 대신 시간을 많이 할당받고 우선순위가 높으면 시간을 짧게 할당 받는다. 따라서 프로세서 중심 프로세스는 우선 순위가 낮은 대신 긴 시간을 할당받고, 입출력 중심 프로세스는 우선순위가 높아 자주 프로세서를 받는 대신 짧은 시간을 할당받는다.

프로세스의 문맥교환(context switching)

문맥 교환의 원인
  1. 트랩 : 부적절한 파일 접근이나, 현재 실행중인 프로세스 오류, 예외 상황에서 치명적인 오류인지 판단하고 치명적일 경우 프로세스 종료 뒤 문맥 교환

  2. 인터럽트

    만약 외부에서 입출력 동작의 종료와 같은 특정 이벤트가 일어난다면 인터럽트가 발생하게 되고, 인터럽트 유형에 따라 각기 다른 처리 루틴으로 제어가 넘어가게 된다. 예를 들면

    • 입출력 인터럽트 : 이벤트를 기다리는 프로세스를 준비 상태로 바꾼 후 실행할 프로세스를 결정

    • 클록 인터럽트 : 현재 실행 중인 프로세스의 할당 시간을 조사해 실행 중인 프로세스를 준비 상태로 바꾸고 다른 프로세스를 실행 상태로 바꾼다.

    이때, 같은 프로세스가 아닌 다른 프로세스를 실행 상태로 바꾸면서 아래 그림 3-11과 같은 문맥 교환이 일어나게 된다.

문맥교환(context switching)

이전 프로세스의 상태 레지스터 내용을 보관하고 다른 프로세스의 레지스터를 적재하여 프로세스 교환하는 과정을 문맥교환(context switching) 이라고 한다.

정확히는 준비 $\rightarrow$ 실행 단계, 실행 $\rightarrow$ 준비 단계, 실행 $\rightarrow$대기 단계에서 발생한다.

이 때 기존의 작업이 끝나지 않은 프로세스은 다음 할당 때 이어가야 하므로, 프로세서의 레지스터 내용을 저장해두고 그림 3-8 처럼 저장한다.

따라서 문맥교환에는 오버헤드가 발생하는데, 메모리 속도, 레지스터 수, 특수 명령어 유무에 따라 오버헤드 크기가 다르며, 최대한 문맥교환을 줄이게 프로그래밍하는 것이 좋다.

문맥교환이 발생되면 종료되는 프로세스는 사용자가 아닌 커널에게 제어가 넘어가며 아래와 같은 문맥 교환이 일어나게 된다.

스레드의 개념과 상태 변화

스레드(thread)란?

프로세스의 제어 부분의 실행단위를 스레드(thread)이라고 하며, 하나의 프로세스는 여러 스레드로 나눌 수 있다.

같은 프로세스의 스레드들은 프로세스의 직접 실행정보를 제외한 나머지 프로세스 관리 정보를 모든 스레드가 공유한다.

그림 3-12는 각 스레드가 프로그램 카운터(PC), 스택 포인터(SP), 지역 데이터, 스택 등을 독립적으로 가지지만, 코드 , 전역 데이터, 힙을 다른 스레드와 공유하는 것을 보여준다.

스레드들은 보통 다른 프로시저를 호출하므로 별도의 스택이 필요하고, PC를 나눔으로써, 동시에 코드의 여러 부분을 실행할 수 있게 된다. 하지만 이 때문에 공유 데이터의 손상이나 이상동작을 조심해야한다.

스레드들이 프로세스 속성의 일부를 공유하는 것을 경량 프로세스(LWP, Light Weight Process), 전통적인 프로세스 하나당 스레드 하나인 경우를 중량 프로세스(HWP, Heavy weight Process)라고 한다.

스레드의 이점

한 프로세스에는 하나 이상의 스레드가 존재할 수 있으며, 이들은 공동의 목적을 위해 병렬로 수행하며, 프로그램의 서로 다른 부분을 동시 실행할 수 있다.

이점은 다음과 같다.

  1. 사용자 응답성 증가: 응용 프로그램이 작업을 수행중이여도, 다른 스레드를 통해 사용자의 응답을 처리할 수 있다.

  2. 프로세스의 자원과 메모리 공유 가능: 스레드들이 프로세스 자원과 메모리를 공유하므로 시스템 성능이 향상된다.

  3. 경제성이 좋음: 프로세스 생성보다 스레드 생성이 문맥 교환 오버헤드가 적다.

  4. 다중처리(multiprocessing)으로 성능과 효율 향상: 각 스레드를 여러 프로세서에서 병렬로 실행하여 성능과 효율성을 높일 수 있다.

스레드 제어블록(TCB, Thread Control Block)

같은 프로세스의 스레드들은 그림 3-13과 같이 주소 공간을 공유한다. 그림 3-19는 더욱 자세한 스레드 제어블록에 관한 그림이다.

한 프로세스는 여러 스레드를 가지고 있으므로, PCB 내에는 여러 TCB의 리스트를 가진다.

스레드 제어블록(TCB, Thread Control Block)은 다음과 같은 내용을 포함하고 있다.

  • 실행 상태: 프로세서 레지스터, 프로그램 카운터, 스택 포인터

  • 스케줄링 정보: 상태, 우선순위, 프로세서 시간

  • 계정 정보, 스케줄링 큐용 모니터들, PCB를 포함하는 포인터 등

스레드의 상태 변화

프로세서 하나에 스레드가 항상 하나만 실행되므로 프로세스처럼 상태 변화가 존재한다.

스레드 생성에는 운영체제가 아니라 프로세스가 스택과 레지스터를 제공하므로, 프로세스의 생성과 종료보다 오버헤드가 적다.

스레드 한개가 대기 상태로 변하면 전체 프로세스의 스레드가 대기 상태로 변하지 않고 다른 스레드 하나가 실행상태되므로, 병렬처리가 가능하다.

다만, 프로세스들과 달리 스레드들은 한 프로세스 내의 메모리를 공유하므로, 보호, 보안 문제가 발생할 수 있지만, 보통 프로세스 하나는 한 사용자만 사용하므로, 보통은 문제없다.

다중 스레드(multithread)

DOS 같은 과거의 운영체제를 제외한 현대 운영체제는 단일 프로세스에서 단일 스레드 실행과 다중 스레드 실행을 둘 다 지원한다. 그림 3-14는 이러한 스레드의 예시이다.

다중 스레드(multithread)는 자원을 공유하는 특성상 자원 생성과 관리의 중복성을 최소화하여 실행능력이 향상될 수 있고, 커널이 개입하지 않고 독립적으로 실행할 수 있어 서버에서 많은 요청을 효과적으로 처리할 수 있다.

다중 스레드에서는 그림 3-15와 같이 데이터를 공유한다.

전역 데이터가 바뀌면 다른 스레드에서 확인 가능하며 힙의 내용 또한 공유된다. 이러한 공유 특성 덕분에 스레드 생성, 스레드 간 자원 및 문맥 교환, 스레드 종료가 훨씬 빠르고, 병렬 처리로 성능을 극대화 할 수 있다.

스레드 사용례

다중 스레드는 사용자 수준에서 적용하여 운영체제와 무관하여 속도가 매우 빠르고 비동기적 요소를 구현할 수 있다. 예를 들면, 스레드 하나는 사용자의 입력을 받아들이고 다른 스레드는 다음 명령을 신속하게 준비할 수 있다.

그림 3-16처럼 워드 편집기에서 주기적으로 진행되는 자동저장 또한 이런식으로 동작한다.

현재 실행중인 스레드를 대기 상태로 바꾸고 제어를 다른 스레드로 옮기는 상태 변화로 많은 요청을 효과적으로 처리할 수 있다. 그림 3-17은 웹 브라우저에서 스레드 한개가 이미지, 텍스트를 로딩하는 동안 다른 스레드는 네트워크에 연결하여 데이터를 검색할 수 있다.

만약 공유메모리가 있는 다중 처리 시스템에서는 프로그램을 공유 메모리에 저장하고 각 프로세서에 스레드를 할당하여 병렬처리하면 더욱 크게 성능을 향상시킬 수 있다.

하지만 이러한 사용자 수준 스레드는 커널 하나를 통해서만 시스템 호출이 가능하므로 시스템 호출의 경우 병목현상이 일어날 수 있다.

수준별 스레드와 스레드 구현

스레드는 다음과 같이 세 가지 형태로 구현할 수 있다.

  • 사용자 수준 스레드(user-level thread) : 다대일(n:1) 매핑

    • 스레드 라이브러리를 이용하여 작동하는 형태
  • 커널 수준 스레드(kernel-level thread) : 일대일(1:1) 매핑

    • 커널(운영체제)에서 지원하는 형태
  • 혼합형 스레드(multiplexed thread) : 다대다(n:m) 매핑

    • 이 둘을 혼합한 형태

사용자 수준 스레드(user-level thread)

사용자 수준 스레드는 스레드 라이브러리를 통해 구현하며, 커널 입장에서는 다중 스레드로 보이지 않고 프로세스 하나로 본다. 즉 스레드 교환에 커널이 개입하지 않고, 커널 수준 스레드 하나에 사용자 수준 스레드 여러개가 매핑되므로 다대일 스레드 매핑이라고도 한다.

스레드 라이브러리는 스레드의 생성과 종료, 메시지 전달, 스케줄링과 문맥 등 정보를 보관하며 POSIX 표준안 스레드 확장판인 Pthread, Win32 thread, JAVA thread API를 사용한다.

장점 세부
이식성이 높음 커널 독립적 스케줄링으로 운영체제에 무관
오버헤드가 적음 커널 호출이 없으므로, 커널 영역의 오버헤드가 줄어듦
유연한 스케줄링이 가능 커널이 아닌 스레드 라이브러리에서 스레드 스케줄링을 제어하므로 응용 프로그램에 맞게 스케줄링을 할 수 있다.
단점 세부
시스템의 동시성을 지원하지 않음 스레드가 아닌 프로세스 단위로 프로세서를 할당해 다중 처리 환경을 갖춰도 스레드 단위로 다중처리 불가. 또한, 프로세스 내의 스레드 한개가 대기 상태가 되면 이 중 어떤 스레드도 실행 불가능
확장에 제약이 따름 커널이 한 프로세스에 속한 여러 스레드에 프로세서를 동시에 할당 불가능하여 다중 처리 시스템 규모 확장 불가
스레드 간 보호 불가능 스레드 간 보호에 커널의 보호 방법을 사용할 수 없다. 스레드 라이브러리에서 해당 기능 지원해야 함.

커널 수준 스레드(kernel-level thread)

사용자 수준 스레드의 한계를 극복하고 커널이 스레드와 관련된 모든 작업을 관리하는 방식, PCB와 TCB를 커널에서 관리한다.

한 프로세스에서 다수의 스레드가 프로세서를 할당받아 병행 수행이 가능하고, 스레드 한개가 대기상태가 되면 동일한 프로세스에 속한 다른 스레드로 교환 가능하다.

스레드가 생성되거나 교환될 때 커널 스레드가 생성되어 사용자 스레드와 1:1 매핑된다.

장점 세부
커널 지원 가능 사용자 수준에 비해 커널 지원이 자유롭다
스레드 병행 수행 커널이 각 스레드를 개별적으로 관리하여 동일 프로세스 내 스레드들이 병행 수행 가능
시스템 동시성 지원 동일 프로세스 내의 스레드 중 하나가 대기 상태가 되더라도 다른 스레드를 실행 할 수 있다
단점 세부
오버헤드 커짐 커널 영역으로 전환하는 오버헤드 발생, 스케줄링, 동기화에 더 많은 자원 필요
어려운 구현 고급 멀티스레딩 기술 필요.
이식성 낮음 각 운영체제 마다 다른 구현이 필요하고, 운영체제에 의존함

혼합형 스레드(multiplexed thread)

사용자 수준 스레드와 커널 수준 스레드를 혼합한 구조로, 양 측 단점을 극복하기 위해 제안되었다.

각 사용자 수준 스레드는 다수의 경량 프로세스(LWP)와 N:M 매핑되고, 이러한 경량 프로세스는 커널 수준 스레드와 1:1 매핑된다.

커널 수준 스레드는 디스패치하고 스케줄링하여 프로세서에서 실행되고, 경량 프로세스는 시스템 호출로 생성해 커널 영역에서 커널이 독립적으로 스케줄링하여 다중 처리 시스템에서는 병렬로 실행한다.

장점 세부
시스템 동시성 문제 해결 스레드 단위로 다중처리 가능. 또한, 프로세스 내의 스레드 한개가 대기 상태가 되면 다른 스레드가 실행 상태로 전환가능
성능 최적화 스레드 라이브러리의 최적 성능을 위해 커널이 경량 프로세스 수 동적 조절
자유로운 매핑 변환 병행 실행이 의미가 없는 경우 다대일 매핑으로 바꾸거나 스레드 풀링을 이용하여 일대일 매핑으로 오버헤드를 줄일 수도 있다.

경량 프로세스가 자원과 입출력 대기를 하므로, 프로세스는 입출력 완료까지 기다릴 필요없다.

스레드 풀링(thread pooling): 시스템이 미리 생성한 스레드의 풀을 응용 프로그램에 제공하여 스레드를 효율적이게 사용할 수 있는 방법, 스레드 생성 오버헤드 감소, 스레드 수 제한으로 인한 일정한 성능 등의 장점이 있다.

단점 세부
   

다중 처리, 다중 프로그래밍, 다중 작업, 다중 스레드