[Operating System] Chapter 4

이한량·2024년 4월 7일

Operating System

목록 보기
4/12
post-thumbnail

1. Processes and Threads

  • 프로세스의 특성

    1). Resource Ownership : 프로세스는 프로그램 코드, 데이터, 스택 및 PCB에 정의된 속성들을 포함하는 가장 주소 공간을 포함한다. 이러한 집합체를 프로세스 이미지라고 한다. 프로세스 이미지는 프로세스가 실행중에 필요로 하는 모든 정보를 담고 있다. OS는 각각의 프로세스의 독립성을 유지하여 보호 기능을 수행한다.

    2). Scheduling / Execution : 프로세스는 실행 상태와 디스패치 우선순위를 갖는다. 이런 속성은 프로세스가 어떻게 CPU에 의해 실행될지를 결정하는 데 중요하다. OS는 이런 프로세스의 특성을 기반으로 스케줄링과 디스패치 작업을 수행한다.

  • Thread : 스레드는 OS가 프로세스 내에서 독립적으로 스케줄링할 수 있는 작업의 최소 단위이다. 쓰레드의 특징은 다음과 같다.

    1). Lightweight (경량성) : 스레드는 프로세스에 비해 실행, 종료, Context Switch가 빠르고 성능면에서 우수하다.

    2). 공유 메모리 : 하나의 프로세스 내의 스레드들은 Code, Data Segment 등과 같은 프로세스 자원들을 공유한다. 따라서, 한 스레드가 메모리 상의 데이터 항목을 변경하면, 다른 스레드들은 그 항목에 접근할 때 변경된 결과를 볼 수 있다.

    3). 독립적인 실행 흐름 : 하나의 프로세스 내에 존재하는 여러 스레드들은 각각 자신만의 실행 흐름을 갖고, 레지스터 상태 또한 독립적이다. 각 스레드는 독립적인 실행 경로와 PC를 갖기 때문에 만약 하나의 스레드가 중단되거나 대기 상태가 되더라도, 다른 스레드는 계속 실행될 수 있다.

프로세스와 쓰레드

1). Process \rarr Resource Ownership : 리소스 소유의 단위

2). Thread \rarr Scheduling / Execution : Thread는 디스패치의 단위 (실행 단위 혹은 light process)

  • Thread의 장점과 단점

    1). 장점

    1-1). 기존 프로세스에서 새 스레드를 생성하는데 걸리는 시간은 새로운 프로세스를 생성하는 것보다 훨씬 적다.

    1-2). 스레드를 종료하는 데 걸리는 시간은 프로세스를 종료하는 것보다 적다.

    1-3). 동일한 프로세스 내의 두 스레드 간에 전환 (Context Switch)에 걸리는 시간은 프로세스 간 전환 시간보다 적다.

    1-4). 스레드는 다른 실행 프로그램 간의 통신 효율성을 향상시킨다. OS에서 서로 다른 프로세스 간의 통신은 커널의 개입이 필요하다. 하지만 동일한 프로세스 내의 스레드들은 메모리와 파일을 공유하기 때문에, 커널 호출 없이 서로 통신이 가능하다.

    2). 단점

    2-1). 동기화 문제 : 스레드 간의 자원 공유로 인해, 여러 스레드가 동시에 같은 데이터를 수정하려고 할 때 데이터 무결성이 손상될 수 있다. \rarr Mutual Exclusion으로 극복 가능

    2-2). 디버깅의 어려움 : 멀티스레딩 프로그램은 디버깅이 더 어렵다. 스레드의 비동기적인 특성으로 인해 발생하는 문제는 일관적으로 발생하지 않을 수 있다.

    2-3). 설계 복잡성 : 멀티스레딩을 사용하는 프로그램은 올바른 동기화 메커니즘을 설계하고 구현해야 하므로, 복잡하다.

  • Multi Threading : 프로세스 내에 존재하는 여러 스레드가 동시에 실행될 수 있도록 하는 기술이다. 단일 스레드 실행과 달리 프로세스의 작업 병렬 처리를 위해 고안된 기법으로, 이런 멀티 스레딩 기법으로 인해 작업을 병렬로 처리할 수 있으므로, 애플리케이션의 반응성과 성능을 크게 향상시킬 수 있다.

    1). Foreground and background work : 예를 들어, 스프레드시트 프로그램에서 하나의 스레드가 메뉴를 표시하고, 사용자의 입력을 읽는 동시에 다른 스레드가 사용자 명령을 실행하고 데이터를 업데이트 할 수 있다.

    2). Asynchronous processing : 워드 프로세서 프로그램을 예로 들어보자. 워드 프로세서는 갑자기 컴퓨터가 꺼져 작업한 내용이 모두 사라지는 등의 상황을 방지하기 위해 자동 저장 제공한다. 이때 스레드가 사용되는데, 이 스레드의 역할은 정해진 시간마다 현재 문서의 상태를 디스크에 저장하는 것이다. 이 작업은 메인 작업 흐름과 독립적으로 이루어진다. 이것이 비동기 프로세싱이다.

    		** 동기적 처리 : 작업이 순차적으로 처리되는 것
       ** 비동기적 처리 : 어떤 작업이 작동하는 것과 별개로 
       독립적인 다른 작업이 동시에 처리되는 것.

    3). Speed of execution : 멀티 스레드 프로세스는 한 배치의 데이터를 계산하는 동안 다음 배치를 장치에서 읽을 수 있다. 따라서 한 스레드가 I/O작업으로 인해 데이터 배치를 읽는 동안 차단될 수 있지만, 다른 스레드는 실행될 수 있다.

    4). Modular program structure : 다양한 활동을 포함하거나 다양한 입력을 받는 동시에 작업을 해야하는 프로그램을 스레드를 사용하여 설계 및 구현하여야 한다.

2. Threads

OS에서 스레드를 지원하는 경우, 스케줄링과 디스패칭은 스레드 기준으로 이루어진다. 따라서 실행과 관련된 대부분의 상태 정보는 스레드 수준의 데이터 구조에서 유지된다. 만약 프로세스 내의 모든 스레드에 영향을 미치는 작업이 있을 땐, OS가 프로세스 수준에서 관리를 하게 된다.

  • Suspension (중단) : 한 프로세스의 주소 공간을 주 메모리에서 스와핑하여 다른 프로세스를 위한 공간을 만든다. 프로세스 내의 모든 스레드가 동일한 주소 공간을 공유하기 때문에, 이런 작업이 이루어지면 모든 스레드가 동시에 중단된다. 마찬가지로, 프로세스의 종료는 해당 프로세스 내의 모든 스레드를 종료한다.

  • Threads State : Threads 관점에서 Suspend는 고려하지 않아도 된다. Suspend state는 프로세스 수준의 개념이기 때문이다. 특히, 프로세스가 Swapped out 될 때 해당 프로세스의 모든 스레드도 같이 스왑 아웃된다. 이는 모든 스레드가 프로세스의 주소 공간을 공유하기 때문이다. OS는 프로세스 상태전이와 마찬가지로, Threads state를 이용해 스레드의 생명 주기를 관리한다.

    1). Spawn (생성) : 새로운 프로세스가 생성될 때, 해당 프로세스의 스레드도 같이 생성된다. 이후 프로세스 내의 스레드는 동일한 프로세스 내에서 다른 스레드를 생성할 수 있으며, 새 스레드에게 명령 포인터와 인수를 제공한다. 새 스레드는 자신만의 레지스터 컨텍스트와 스택 공간을 할당받고, 준비 큐에 배치된다.

    2). Block (차단) : 스레드가 특정 이벤트 발생을 기다려야 할 때(I/O Interrupt와 같은), Blocked로 상태 전이된다. 프로세서는 동일한 프로세스 또는 다른 프로세스의 다른 준비된 스레드의 실행으로 전환한다.

    3). Ready (준비) : 스레드를 차단한 이벤트가 발생하거나, 스레드가 생성된 뒤 실행할 준비가 완료되었을 때, 스레드는 준비 큐로 이동한다.

    4). Terminate (종료) : 스레드가 완료되면, 해당 스레드에 할당된 리소스 (레지스터 컨텍스트, Data 스택...)이 회수된다.

3. Types of Threads

  • User-Level Threads (ULTs) : 스레드 관리의 모든 작업이 애플리케이션에 의해 수행되며, 커널은 스레드 관리에 관여하지 않는다. 모든 애플리케이션은 ULT 관리를 위한 스레드 라이브러리 (스레드 spawn, terminate, 스레드 간 통신, 스레드 실행 스케줄링, 스레드 컨텍스트 저장 및 복원...)를 통해 멀티 스레드로 프로그래밍 될 수 있다.

1). 기본적으로 애플리케이션은 단일 스레드로 실행을 시작한다. 이 애플리케이션과 스레드는 커널에 의해 관리되는 단일 프로세스에 할당된다.

2). 애플리케이션이 실행중일 때, 애플리케이션은 스레드 라이브러리 내의 spawn 호출하여 동일한 프로세스 내에 새로운 스레드를 생성할 수 있다.

  1. 스레드 라이브러리는 새 스레드를 위한 데이터 구조를 생성한다음, 어떤 스케줄링 알고리즘을 통해 같은 프로세스 내의 준비 상태인 스레드 중 하나에게 제어(실행 흐름)를 전달한다. spawn 함수는 제어를 받아 새로운 스레드를 생성하고, 생성된 스레드 또는 기존의 다른 준비 상태의 스레드에 제어(실행 흐름)을 전달한다.

    ** 제어를 전달한다? : 프로그램의 실행 흐름이나 작업의 수행 권한이 
    넘어간다는 말이다. 즉, 어떤 함수, 루틴, 메서드, 스레드 또는 프로세스가 
    실행을 시작하거나 계속하도록 실행 제어권을 넘기는 것이다.
    제어에는 CPU의 리소스 사용 권한이 포함된다.

위 그림을 예시로 ULT에서 프레세스 스케줄링과 스레드 스케줄링의 관계를 설명할 수 있다.

1). (a) \rarr (b) : 스레드 2에서 실행중인 프로세스 B를 차단하는 System call이 발생. 이는 제어를 커널로 전달하게 한다. 커널은 프로세스 B를 차단한 뒤 (Block) 다른 프로세스로 작업을 전환한다. 한편, 프로세스 B의 스레드 2는 여전히 실행 상태에 있다. 이때 스레드 2는 CPU에서 실제로 실행되고 있진 않지만, 스레드 라이브러리에 의해 실행 상태로 간주된다.

2). (b) \rarr (c) : 커널이 프로세스 B의 실행이 준비되었다고 판단하면, 프로세스 B는 Ready State로 상태가 전이된다. 한편, 여전히 프로세스 B의 스레드 2는 여전히 실행 상태에 있다.

3). (c) \rarr (d) : 스레드 2는 스레드 1에 의해 수행되어야 하는 어떤 작업에 도달하여, 스레드 2는 Blocked되고, 스레드 1은 Ready 상태에서 Running 상태로 전환된다. 이때 프로세스 B는 실행 상태이다.

ULT 환경에서 커널과 프로세스사이의 통신과는 별개로 스레드는 스레드 라이브러리에 의해서 관리되며 독립적으로 동작한다. 즉, 커널이 인지하는 프로세스 스케줄링과 ULT 라이브러리의 스케줄링은 서로 독립적이다.

ULT의 장점과 단점

  • 장점

1). 커널 모드 권한이 필요 없는 스레드 전환 : ULT의 모든 스레드 관리 데이터 구조는 단일 프로세스의 사용자 주소 공간 내에 있기 때문에, 스레드 전환을 위한 커널 모드 권한이 필요 없다. 이는 사용자 모드에서 커널 모드로, 커널 모드에서 사용자 모드로 돌아가는 두 번의 모드 전환 오버헤드를 절약한다.

2). 응용 프로그램 특정 스케줄링 : OS 스케줄링 알고리즘에 의존하지 않고 각각의 응용 프로그램의 요구와 목적에 맞는 스케줄링 알고리즘을 선택하고 구현할 수 있다.

3). 모든 OS에서 실행 가능한 ULT : ULT를 지원하기 위해 기본 커널에 변경이 필요하지 않다. 스레드 라이브러리는 모든 응용 프로그램이 공유한다.

  • 단점

1). ULT 환경에선 커널이 스레드의 존재를 인식하지 못하므로, 만약 커널이 프로세스를 Blocking 한다면 시스템 자원을 요청한 스레드 뿐만 아니라, 같은 프로세스 내에 있는 모든 스레드가 대기 상태로 전환된다. (애플리케이션 라이브러리는 스레드를 실행 상태로 간주하지만, 실제로는 대기 상태이다.)

2). ULT 환경에선 커널이 사용자 수준 스레드의 존재를 인식할 수 없다. 즉, 커널은 프로세스 단위로만 작업을 관리하고 할당한다. 따라서 ULT는 커널 수준에서의 멀티스레딩을 활용할 수 없다.

  • Kernel-Level Threads (KLTs) : 스레드 관리의 모든 작업이 커널에 의해 수행된다. 애플리케이션 수준의 스레드 관리 코드가 없으며, 개발자는 스레드를 관리하기 위해서 커널 수준의 기능을 호출하는 Application Programming Interface(API)를 사용한다. 즉, 스레드의 생성, 스케줄링, 동기화 및 종료 등의 모든 관리 작업이 OS의 커널에 의해 이루어진다.

1). 스레드 생성 : 애플리케이션은 커널에 스레드 생성을 요청한다. 이 때, 커널은 필요한 자원을 할당하고 스레드를 위한 고유한 Context(PC, Stack, PCB...)를 설정한다.

2). 스케줄링 : 커널은 시스템 내의 모든 스레드를 관리하며, 스레드 스케줄러를 통해 어떤 스레드가 CPU를 차지할지 결정합니다. 다중 프로세서 시스템에서는 여러 스레드를 동시에 실행할 수 있다.

3). 실행 : 스케줄러에 의해 선택된 스레드가 CPU를 할당받고 실행된다.

4). 동기화 : 여러 스레드가 동시에 실행될 때, 공유 자원에 대한 접근을 조율하기 위해 동기화 메커니즘이 필요하다. (Mutual Exclusive, Semaphore)

5). 커뮤니케이션 : 스레드 간의 데이터 교환과 상태 정보의 공유는 커널을 위해 이루어진다. 커널은 IPC(Inter Process Communication) 메커니즘을 통해 스레드간에 메시지를 전달하거나 데이터를 공유할 수 있게 한다.

6). 종료 : 스레드가 작업을 완료하면, 커널에 종료를 요청한다. 커널은 스레드가 사용하던 자원을 회수하고, 스레드의 상태를 종료 상태로 전이한다.

ULT의 장점과 단점

  • 장점

1). KLT 환경은 커널이 모든 스레드 관리를 담당하기 때문에, 동일한 프로세스 내의 여러 스레드를 프로세서가 스케줄링할 수 있다. 따라서 멀티 프로세서 환경에서 멀티 스레딩 능력을 극대화 할 수 있다.

2). 한 프로세스 내의 스레드가 Blocking 상태가 되거나 Ready 상태에 있을 때(I/O 작업 등으로 인해), 커널은 다른 스레드를 스케줄링하여 프로세서에 할당할 수 있다. 이는 애플리케이션의 반응성과 시스템 전반적인 성능 향상에 도움이 된다.

3). 커널 자체를 멀티 스레드로 작동하도록 할 수 있으므로, OS의 핵심 기능 수행에서도 멀티 스레딩의 이점을 누릴 수 있다.

4). 개발자는 커널이 제공하는 API를 통해 스레드를 관리하기 때문에 스레드 관리의 복잡성이 줄어든다. 이는 프로그래밍을 보다 단순화시킬 수 있다.

  • 단점

1). KLT에서 스레드 간 전환은 커널 모드로의 전환을 필요로 한다. 이는 ULT 방식에 비해 상대적으로 더 많은 시간과 자원을 소모하도록 한다.

2). 커널이 각 스레드를 개별적으로 관리하기 때문에, 스레드마다 별도의 커널 자원(스레드 컨텍스트)를 할당받는다. 이는 많은 수의 스레드가 동시에 활성화되는 시스템에서 자원 활용에 비효율성을 초래할 수 있다. 또한 복잡하고 고도의 스케줄링 알고리즘과 동기화 메커니즘이 필요하다.

3). KLT 구현은 OS의 커널에 의존적이다. 따라서 특정 OS에서 잘 동작하는 KLT 기반의 애플리케이션을 다른 OS로 옮긴다면, 해당OS에서는 정상적으로 작동하지 않을 수 있다.

  • ULT와 KLT 방식 사이의 주요 차이점

    1). KLT 환경은 스레드와 관련된 모든 작업이 커널을 통해 이루어진다. 따라서 한 프로세스 내의 다른 스레드들간의 제어 전환이 발생할 때, 커널 모드로의 전환이 필요하다(Overhead). 반면, ULT 방식에선 이런 작업들이 애플리케이션의 라이브러리를 통해 처리 된다(Overhead 없음).

    2). KLT 방식은 스레드 관리의 복잡성을 OS에 맡기는 대신 높은 오버헤드와 스레드간 전환 속도가 느리지만, 멀티 스레딩의 장점을 극대화 할 수 있다. 반면 ULT 방식은 더 낮은 오버헤드와 스레드간 빠른 전환을 제공하지만, 개발자가 스레드 관리의 복잡성을 직접 다루어야 하며, 멀티 스레딩을 활용할 수 없다.

    ULT \rarr 스레드간 전환 속도 빠름. 커널 수준에서 멀티 스레딩을 활용할 수 없음.

    KLT \rarr 스레드간 전환 속도 느림. 멀티 스레딩을 극대화할 수 있음.

profile
한량 극복 프로젝트

0개의 댓글