관리 메뉴

사과하는 제라스

8. Thread 본문

대학 전공 공부/운영체제

8. Thread

Xerath(제라스) 2022. 11. 19. 02:36

목차

    728x90
    반응형

    Process가 뭐여...?? 이거 되게 추상적인데...

    OS에서

    추상적인 개념으로는...

    1) Scheduling의 단위

    2) 소유하고 있는 자원(Virtual Memory, file 등)에 대한 보호

     

    프로그램과의 관계에서는...

    3) 정적인 단위의 프로그램에 반해 하나의 실행 흐름을 갖고 실행 중인 프로그램

    -> 근데 이거 실행 흐름이 여러 개일 수도 있는데...?!?!?!?!?

    이렇게 프로세스 안에서 실행되고 있는 논리적인 각각의 실행 흐름 => 이게 Thread다!!!

     

    Thread

    - Execution Unit

    - 프로세스 내의 실행 흐름

    - 프로세스보다 작은 단위

    - 프로세스가 제공한 Protection Domain은 없음

    Thread 라는 개념은 왜 생겨남...??

    프로세스를 여러개를 쓸 수는 있는데(Cooperative Process), 각 프로세스는 하나의 실행 흐름만 존재했기에 한번에 하나의 일만을 함.

    -> 한 프로세스를 여러 개로 나눠서 쓰레드화 하면 병렬적으로 작업을 완수할 수 있지 않을까? 허거거거걱!!!대박!

     

    그럼 이게 Cooperative Process와의 차이점이 무엇일까?

    IPC가 필요없어서 비용이 덜 듦 + 프로세스 간의 Context Switching 비용이 들지 않음.

    ∴ 프로세스 내에 Thread를 만드는게 Cooperative Process보다 적은 비용으로 동일한 일을 수행 가능함.

     

    Thread와 CPU 사용률의 관계

     

    * throughput: 통신에서 네트워크 상의 어떤 노드나 터미널로부터 또 다른 터미널로 전달되는 단위 시간당 디지털 데이터 전송으로 처리하는 양

     

    1. Thread 수가 증가할수록 CPU의 사용률이 증가함.(임계값을 지나면 감소하는데, 이는 Thread Switching 비용이 증가하기 때문.)

    2. CPU가 많은 시스템일수록 Thread를 이용하는 것이 유리함.

     

    Process VS. Thread

    Process

    - 하나의 Thread와 같은 실행 흐름을 가짐.

    - 프로세스 간의 메모리는 독립적임 ∴ 서로의 영역에 접근하기 어려움.

    - 프로세스 간의 Switch 비용이 큼

    Thread

    - 하나의 Process에 여러 개의 Thread가 존재함.

    - 프로세스의 Code 영역, Data 영역은 Thread 간에 공유함.(∵Thread들은 같은 VM을 공유하기에 그 안에 있는 Code 영역, Data 영역 또한 공유하는 것임.)

    - Thread들은 같은 Virtual Memory 영역을 공유하기에 Thread 간에 Switch 비용이 적게 듦.

     

    Thread의 구성요소

    Thread도 하나의 실행 흐름이잖슴..? 그래서 실행과 관련되어서 자료구조가 필요함.

     

    1) Thread ID(Thread 식별자)

    2) PC(Program Counter로 현재 실행 중인 Instruction의 주소값임)

    3) Register Set(CPU의 Register값들)

    정보) 레지스터(Register)는 CPU가 요청을 처리하는데 필요한 데이터를 일시적으로 저장하는 다목적 공간. 프로세스 내부에 있는 작은 공간이고 연산 제어, 디버깅 등의 목적으로 사용

     

    4) Stack -> 하나의 논리적인 실행 흐름을 갖기 위해서는 Stack(지역변수, arguments 등이 존재)을 가져야 함.

     

    Thread들이 프로세스에서 서로 공유 중인 것

    1) 프로그램의 Code section

    2) 프로세스의 Data section

    -> Code와 Data는 프로세스 내의 VM에 존재하기에 이를 프로세스 내의 쓰레드들은 공유함.

     

    3) 프로세스에서 open한 File

    -> 정보) 부모 프로세스가 open한 File은 fork를 통해 자식 프로세스에게도 상속이 된다.

    그냥 그렇다구우우~~~~

     

    Multi-Threaded Process(멀티 쓰레드 프로세스)

    단일 쓰레드 VS. 멀티 쓰레드

    멀티 쓰레드 장점이 뭔데...?

    1) Responsiveness: 어떤 부분이 Block되거나 시간이 걸리는 작업을 해도 딴 것들은 실행되고 있기에 유저 입장에선 프로그램이 Interactive하다고 느낌.(뒤에서는 돌고 있지만 앞에서는 수행 중인 모습을 보여주면 오!실행 잘 되는 중이구나 느낌. 비스꾸리하다고 생각)

     

    2) Resource Sharing: 쓰레드들 간에 프로세스의 Memory, 다른 자원들을 공유함.

     

    3) Economy: 새로운 프로세스를 생성하게 되면 VM을 새로 또 생성해야하는데 이보다는 프로세스 내에 쓰레드들을 더 만드는 것이 비용이 적게 들어감.

     

    4) Scalability: 여러 쓰레드가 각각 다른 Processor(=CPU. 같다고 봐도 무방함.)에서 동시에 실행이 가능함.

     

    Multicore Programming

    현재 Processors는 하나의 Chip(=Processor)에 여러 개의 Computing Core를 탑재하는 방식을 씀.

    -> Multicore Processor

     

    멀티쓰레드 프로그래밍은 Multicore 시스템에서도 효율적임.

    Why?

    : 멀티코어 프로세서는 OS에서 각각의 코어들을 하나의 프로세서로 인식하고 스케줄링함.

    -> 각각의 쓰레드에 코어를 할당해서 실행이 가능함.(= 코어들에 쓰레드들을 할당해서 실행이 가능함.)

    -> 이때 하나의 프로세서 안에 있는 코어들은 서로 Cache를 공유함.

    -> 이게 Data, Code 등의 Process 자원을 공유하는 멀티쓰레드 프로그래밍에게도 효율적임.

    (∵ Data, Code를 Cache에 넣어서 공유할 수 있기에 효율적이라는 것이다.)

     

    User Thread VS. Kernel Thread

    Thread를 지원하는 주체에 따라 나뉨.

    User Thread

    : 커널 영역 위에서 지원이 되며, 일반적으로는 User 레벨의 라이브러리를 통해 구현이 됨. 라이브러리에서 쓰레드를 생성하고 스케줄링과 관련된 관리를 해줌.(실행은 OS가 함.)

     

    - 장점: 동일한 메모리 영역에서 쓰레드가 생성,관리가 되므로 이에 대한 속도가 빠름.

    - 단점: 여러 유저 쓰레드 중 하나의 쓰레드가 System Call 요청으로 Block되면 나머지도 싹 다 Block됨.(∵커널은 여러 User Thread들을 하나의 프로세스로 간주하기 때문.)

    Kernel Thread

    : OS에서 Thread를 지원함. -> Kernel 영역에서 쓰레드를 생성하고 스케줄링을 관리함.

    1장에서의 설명 참조

    - 프로세스가 실행 중일 때 같은 메모리에 대하여 각각의 PC값이 커널의 System Call로 인해 호출됨.

    -> 이때 커널은 두 프로세스의 System Call을 같이 처리함.

    ∴ Blocking이 존재 X.

    - 장점: 쓰레드가 System Call에 의해 Block 되어도, 커널은 다른 쓰레드를 실행함으로써 전체적인 쓰레드 Blocking이 없음.

    - 단점: User Thread에 비해 생성, 관리가 느림.

     

    Many-to-One

    : 여러개의 User Thread들이 하나의 Kernel Thread들로 Mapping되는 것. 주로 Kernel Thread를 지원하지 못하는 시스템에서 씀.

     

    - 한계점

    : 한번에 하나의 쓰레드만 커널에 접근 가능함.

    - 하나가 접근하면 나머지는 대기 -> 진정한 Concurrency 지원 불가, 동시에 여러 쓰레드가 System Call 사용 불가

    -> 여러 쓰레드가 하나의 프로세스이기에 멀티프로세서더라도 여러개의 Processor에서 동시 수행이 불가능함.

    One-to-One

    : 각 User Thread 하나하나가 Kernel Thread로 Mapping되는 것. User Thread가 생성되면 이에 따른 Kernel Thread가 생성됨.

     

    - Many-to-One의 문제점 해결

    But,....

     

    - 한계점

    : Kernel Thread도 한정된 자원이기에 무한정 생산 불가능.

    ∴Thread를 생성 or 사용하려 하면 그 개수에 대한 고려가 필요함.

    Many-to-Many

    : 여러 User Thread를 여러 개의 Kernel Thread로 Mapping하는 것. Kerneal Thread는 User Thread 개수보다 적거나 같은 만큼만 생성되어 적절히 스케줄링됨.

     

    -> Many-to-One처럼 Thread Blocking 현상을 걱정하지 않아도 되고, One-to-One처럼 Thread 수에 대한 고민을 할 필요가 없음.

     

    즉, 커널이 적절하게 User Thread와 Kernel Thread 사이의 Mapping을 조절하기에 단점을 보완하고 장점을 유지할 수 있음.

    Thread가 생기면서 OS에 생긴 변화

    1) Process 기반의 OS System Call

    원래는 Process 기준으로 System call Semantics를 작성함.

    -> 근데 이거 Thread 개념을 고려해야 하게 됨.

    ex.

    - fork()-(프로세스 생성하는 시스템 콜) 나 exec()-(새로운 이미지나 바이너리를 올려서 실행하는 시스템 콜) 같은 기능을 Thread에서 지원이 필요해짐

    - 멀티 쓰레드의 경우엔 함께 일하는 쓰레드의 종료가 프로세스보다 복잡해짐.(프로세스는 그냥 종료시켜주면 되지만 쓰레드는 종료 시 자우너 반납을 하면 안된다. 다른 쓰레드들이 실행 중일 수 있잖슴....!!아하!!)

     

    2) Multi-threaded Programming

    : Thread의 스케줄링, 통신 방법, Memory 공간(Stack, Thread-specific Data) 할당 필요해짐에 따라 OS가 더 복잡해짐.

     

    Thread의 이슈: 생성(Creation)

    fork(), exec()라는 시스템 콜에 대해서...

     

    멀티 스레드가 동작중인 프로세스에 대해 fork() 를 호출하게 되면 내부 스레드도 같이 복사되어야 할까?

    - fork

    하나의 Program 내의 Thread가 fork를 호출하면 모든 Thread를 가지고 있는 Process를 만들지,

    아니면 요청한 Thread만을 복사한 Process를 만들지의 문제가 있음.

    -> Linux에서는 2가지 방식의 fork를 만들어서 각각의 경우를 처리하도록 함.

     

    - exec

    fork() 이후 exec()이 호출된다면 exec() 새로운 프로세스가 실행되는 것이기에 모든 스레드를 복사할 이유가 없음.

    exec()이 호출되지 않으면 모든 스레드를 복사하는 것이 의미를 지님.

     

    정보) 새로운 프로세스를 만드는 법: fork를 통해 부모 프로세스를 복사해서 만들고, 이후 exec을 통해서 초기화하여 아예 다른 새로운 프로세스를 만듦.

    Thread의 이슈: 종료(Cancellation)

    Thread Cancellation: Thread의 작업이 끝나기 전에 외부에서 작업을 중지시키는 것

     

    1) 하나의 Thread에서 중지 명령이 결국 다른 Thread의 모든 작업을 중지시켜야 하는 경우

    -> ex. 웹에서 이미지 읽기 도중 stop 버튼으로 취소함. 이때, Image를 읽어오는 Thread도 중지되어야 함.

     

    2) 자원이 Thread에게 할당된 경우의 Cancellation 문제

    : System의 자원을 사용하다가 사용 중인 Thread 하나가 중지되어도 해제할 수가 없음(∵ 다른 Thread가 그 자원 사용 중일지도 모르기 때문.)

     

    Thread Pools

    배경: 쓰레드가 동작하는 시간보다 쓰레드를 새로이 만드는 시간이 더 긴 경우가 생김. 쓰레드는 시스템의 자원이기 때문에, 시스템의 동작을 보장하는 최대한의 쓰레드 수도 제한이 필요함.

     

    그래서! 만들었다! Thread Pool!!!!!!!

     

    이..이게 뭔데...??

     

    프로세스가 새로이 실행될 때, 정해진 수 만큼의 쓰레드를 만들어서 Pool에 할당함. -> 이후, 새로운 쓰레드가 필요 시 Pool에서 가져오고 끝나면 Pool에 다시 반납함.

     

    - Pool을 통해서 제한된 수의 쓰레드를 관리하면, 그렇지 않은 경우보다 쓰레드 생성 시간 적게 걸림.

    - 많은 쓰레드 생성에 따른 시스템 부하를 줄일 수 있음.

    - Pool에서 관리할 쓰레드 수는 시스템의 메모리 or 예상되는 작업의 수를 통해 어림짐작으로 결정함.

     

    Thread 간의 IPC

    멀티쓰레드 프로그래밍은 쓰레드 간의 통신도 필요함.

     

    이때 쓰레드 간의 IPC 구현은 어떻게 할까?

     

    동일한 프로세스 내의 쓰레드들은 같은 프로세스의 Data 영역을 공유하기에 자연스레 VM의 Shared Memory를  공유가능함.

     

    -> Shared Memory

    -> IPC가 최소화 됨.

    -> 쓰레드들 간의 자원 공유로 인해 가능해짐.

     

    다른 프로세스에 존재하는 쓰레드들 간에는 프로세스들 간의 통신 방법과 비슷함. -> 성능 안 좋음.

    ∴ 이런 통신이 빈번하다면 프로그램의 설계가 잘못되었음을 느껴야 함.

     

     

    'OS 입장에서프로세스와 쓰레드를 관리해주는 메커니즘은 어떤 차이가 있을까?'를 알아둘 필요가 있다.

     

    728x90
    반응형

    '대학 전공 공부 > 운영체제' 카테고리의 다른 글

    10. Synchronization(동기화)-2  (1) 2022.12.01
    9. Synchronization(동기화)-1  (0) 2022.11.24
    7. IPC(Inter Process Communication)  (0) 2022.11.17
    6. CPU Scheduling  (1) 2022.11.02
    5. Computer Architecture  (0) 2022.10.11