[PintOS] - Thread

Junyeong Fred Kim·2021년 12월 28일
0

운영체제

목록 보기
7/27

첫번 째 과제 수행(Alarm System Call)을 수행하기 위해 알아야할 Thread에 대해 알아보자.

👉 프로세스의 문제점

프로그램이 메모리에 로딩되어 실행 중인 상태인 프로세스(Process)를 기반으로 하는 멀티태스킹은 여러 프로세스를 동시에 실행시킴으로써 CPU(Central Processing Unit)의 활용률과 시스템의 처리율을 높였다. 그 결과 다양한 멀티태스킹 어플리케이션이 등장하게 되었지만 다음과 같은 여러 문제점들이 제기되었다.

프로세스 생성에 따른 큰 오버헤드

프로세스마다 독립적인 메모리 공간을 갖기 때문에 자식 프로세스에게 부모 프로세스와는 별도로 메모리를 할당할 공간에 부모 프로세스를 복사하게되어 프로세스 생성에 많은 시간이 소요된다. 운영체제도 새로 생성되는 프로세스를 위해 PCB(Process Control Block), 페이지 테이블 등 프로세스 관리를 위한 구조체를 생성하는 데 많은 시간이 걸린다.

비효율적인 프로세스 컨텍스트 스위칭

  • CPU가 현재 실행 중인 프로세스의 논리 주소와 물리 주소의 페이지 테이블을 새로 실행될 프로세스의 페이지 테이블로 교체하는 시간
  • 현재 실행 중인 프로세스의 컨텍스트(ex. CPU 레지스터 등)를 PCB에 저장하고 새로 실행될 프로세스의 PCB로 부터 컨텍스트를 CPU로 옮기는 시간
  • 캐시 메모리에 들어 있는 현재 프로세스의 코드나 데이터를 지우고 새로 실행될 프로세스의 코드와 데이터를 로딩하는 시간

위와 같이 현재 실행 중인 프로세스를 중단시키고 다른 프로세스를 실행시키는 컨텍스트 스위칭에 따른 시공간적 오버헤드가 크다.

프로세스 간 통신의 어려움

프로세스들은 각자 독립된 공간을 가지고 있기 때문에 다른 프로세스의 메모리에 접근할 수 없다. 그래서 프로세스들은 공유 메모리(sharded memory), 신호(signal), 파이프(pipe), 파일(file), 소켓(socket), 메시지 큐(message queue), 세마포(semaphore), 메모리 맵 파일(memory mapped filed, MMF) 등 다양한 방법을 통해 커널 메모리나 커널에 의해 마련된 제 3의 메모리 공간을 이용하여 데이터를 주고 받았다.

하지만 위 기능들은 다음과 같은 이유로 사용에 있어 여러 어려움이 있다.

  • 거의 모두 커널의 직접적인 지원을 받음
  • 운영체제에 따른 호환성이 부족함
  • 개념적으로 복잡하며 코딩이 어렵고 실행 속도가 느림

👉 스레드의 출현 목적

위와 같은 프로세스의 문제점들을 해결하고자 하는 필요성이 증가함에 따라 스레드 (thread)라는 새로운 실행 단위가 출현하게 되었다.

  • 프로세스보다 크기가 작은 실행 단위의 필요
  • 프로세스의 생성 및 소멸에 따른 오버헤드 감소
  • 빠른 컨텍스트 스위칭
  • 프로세스들의 느린 실행 속도와 통신 시간 개선
  • 복잡한 방법으로 인한 코딩 등의 어려움 해소

👉 스레드의 상태와 작동

1. 상태(state)

스레드는 프로세스처럼 생성부터 소멸까지 여러 상태를 거치는 Life cycle을 가지고 있다. 운영체제마다 조금씩 다르게 구현되어 있지만 일반적으로 준비(ready state), 실행(running state), 대기(bloked state), 종료(terminated state)의 4가지 상태를 가지며 이 정보는 TCB(Thread Control Block) 구조체에 저장된다.

준비 상태 (ready state)

  • 스레드가 생성된 후 스케줄 되기를 기다리는 상태
  • 실행 상태의 스레드의 할당된 시간이 경과되거나 스레드 스스로 CPU 사용을 양보하는 경우
  • 대기 상태의 스레드가 입출력이 완료되거나 타임아웃을 통해 자원을 획득하는 경우

실행 상태 (running state)

  • 준비 상태의 스레드가 스케줄링 되어 현재 CPU에 의해 실행된 경우

대기 상태 (blocked state)

  • 스레드가 입출력을 요청하거나 sleep()과 같은 시스템 호출로 인해 커널에 의해 중단된 경우

종료 상태 (terminated state)

  • 스레드가 스스로 종료하거나 또는 프로세스가 종료된 상태

2. 작동 (operation)

스레드의 존재를 인식하고 다룰 수 있는 커널이나 스레드 라이브러리에 의해 이루어지는 작동은 생성(create), 조인(join), 양보(yield), 종료(termination) 등이 있다.

스레드 생성(thread create)

프로세스와 마찬가지로 스레드는 새로운 스레드를 생성할 수 있다. 그러나 부모 스레드가 종료한다고 자식 스레드도 종료되는 것은 아니기 때문에 프로세스의 부모자식 관계에 비하면 스레드의 부모자식 관계의 의미는 크지 않다.

스레드 조인(thread join)

한 스레드가 다른 스레드가 작업을 끝내고 종료할 때까지 기다리는 것이 조인이다. 아무 스레드나 다른 스레드를 조인할 수 있으나, 일반적으로 부모 스레드가 특정 작업을 위해 자식 스레드를 생성하여 일을 시키고 자식 스레드가 작업을 완료하기를 기다릴 때 주로 사용한다.

스레드 양보(thread yield)

실행 중인 스레드가 스스로 CPU를 다른 스레드에게 양보하기 위해 실행을 중단하는 행위가 양보이다. 양보한 스레드는 커널에 의해 준비 상태(ready state)가 되어 준비 큐(queue)에 들어가고, 준비 큐에 있는 스레드 중 하나가 스케줄링되어 실행된다. 이 기능은 매우 비싼 자원인 CPU를 스스로 다른 스레드에게 양보함으로써 효율적으로 사용하기 위해 만들어졌다.

스레드 종료(thread termination)

프로세스의 종료는 exit() 시스템 호출을 호출하여 해당 프로세스를 비롯한 모든 스레드가 종료되는 것을 의미한다. 이와 달리 스레드 종료는 pthread_exit()과 같이 스레드만 종료시키는 함수를 호출하는 경우이다. 이 때, 부모 스레드의 종료와 자식 스레드의 종료는 무관하며, 프로세스에 속한 마지막 스레드가 종료될 때 프로세스가 종료된다. 스레드가 다른 스레드를 생성할 수는 있었지만 강제로 종료할 수 있는 방법은 기본적으로 제공되지 않고 약속된 신호를 통해 스스로 종료하도록 설계하는 작업이 필요하다.

profile
기억보다 기록

0개의 댓글