운영체제(4) - Multi Thread Programming(1)

‘운영체제’를 공부하여 정리한 내용입니다.

1. 개요

Thread란?

  • Thread는 한 프로세스에 속한 다른 스레드들과 일부 자원을 공유하여 동작하는 형태의 Working entity이다.

    • 공유하는 것: Text(코드), Data(전역 변수 등), 열린 파일이나, 신호와 같은 운영체제 자원들, 그리고 Heap(동적 할당한 값들)
    • 각자가 가지는 것: Thread ID, PC, 레지스터 집합, 스택(지역 변수는 공유하지 않는다.)
  • 재밌는 점

    • 각 Thread에서 동적할당 하면 이는 같은 Heap 영역을 사용하게 된다.
    • 그리고 Thread가 종료되어도 이 Heap 공간에 채워진 값들은 반납되지 않는다.(메인 process가 돌아가고 있는 이상)

장점

  • 한 응용 프로그램이 동작할 때, 사용자와 상호작용을 하는 쓰레드를 따로 두고, 다른 쓰레드는 작업을 처리하도록 하게 하여 응답성을 증가시키는 것이 가능하다.
  • 자원을 공유하기 때문에, IPC 등의 작업보다 더 직관적으로 공유하는 자원에 대한 작업을 진행하는 것이 가능하다.
  • 자원을 공유하는 thread는 process보다 생성되는데에 들어가는 비용이 싸다.
  • Multi Processing 에서는 그 효용성이 더욱 증가한다. 병렬 처리에 이용할 수 있기 때문에.

다중 코어 프로그래밍

  • 고려해야 하는 점
    • 작업 나누기
    • 균형
    • 데이터 분리: 각 테스크가 접근하는 데이터도 개별 코어에서 접근할 수 있도록 잘 나누어져야 한다.
    • Test and Debuging: 되게 어려워진다.

2. multi Thread models

이 내용이 말하는 것이 무엇인지 감을 잡아보자.

  • Thread가 여러개 생성이 되는 상황을 가정하자

    • 일반적으로 우리가 사용하는 것은 User mode에서 도는 Thread이다.
    • 그런데 알다시피, 우리의 프로그램은 절대 kernel 모드의 지원이 필요한 경우가 매우 많다.
    • 이 때 우리가 multi core 프로그램을 사용하고 있다고 생각해보자.
    • 그러면 각 thread가 병렬적으로 돌다가 system call을 호출하면 다들 kernel 모드에서 도는 thread에게 도움을 요청하게 된다. (user 모드에서 도는 thread는 Privileged instruction을 실행할 수 없기 때문에)
    • 이 때, 서버에서는 이 thread들의 동작을 위해서 얼마만큼의 thread를 매핑 시켜 놓고 있어야 하는가가 바로 이 문제의 핵심이다.
    • Q. 솔직히 thread도 레지스터 집합을 다 가지고 stack도 가지고 있는데 왜 이런 작업을 해야 하는지는 모르겠다. 자신의 레지스터 집합에서 mode bit를 0으로 바꾸고 stack을 사용해서 현재 값들을 후퇴시킨 뒤에 kernel 코드에 있는 ISR로 뛰면 되는 것 아닌가? 답을 알게 되면 추가하겠다.
    • cf) 만약 처음 thread라는 것이 고안될 때, Mode bit에 대한 고려 없이 만들어졌다면 추가적인 kernel thread를 만드는 작업이 필요하긴하다.

Multi thread model 종류

  • Many-to-One Model

    • 아무리 User thread가 많이 생성되어도, 하나의 kernel thread만 대기 시키는 방법
    • 이 경우는 커널이 프로세스가 가지고 있는 thread에 대한 정보를 파악하지 않고 있다고 생각할 수 있다.
    • 이렇게 되면 User thread들이 동시에 System call을 호출할 때는 코어가 아무리 많아도 순차적으로 실행된다.
    • 병렬성의 이점을 살릴 수 없다.
  • One-to-One Model

    • 각 user thread 당 kernel thread를 생성 시켜두는 것
    • kernel thread를 매번 생성하게 되면, 그 오버헤드가 크다.
    • 일반적으로 이 모델을 쓰지만, 쓸 때 thread 생성 최대 개수를 제한한다.
  • Many-to-Many Model

    • User thread의 개수와 같거나 적은 Kernel thread에 사상한다.
    • 이 경우는 사용자가 User thread를 자유롭게 생성할 수도 있고, 최대한의 병렬성을 유지할 수도 있다.
  • 현대의 OS

    • 일반적으로 One-to-One Model, Many-to-Many Model 두개를 섞어서 사용한다.
      • 이를 두 수준 모델이라고 한다.
      • 프로그래머가 명시적으로 명령하는 것이 가능하다.

3. Thread Library

  • (추후 업데이트)

4. Threading issues

multi thread가 돌때, fork()와 exec()을 호출할 때

  • 모든 스레드가 복사되는 버전이 있고
  • 아닌 버전이 있다
    • 주로 exec()을 같이 사용할 때 이 버전을 사용한다.

Cancellation

  • 비동기식 취소
    • 어떤 thread가 다른 thread를 그냥 종료시켜 버리는 것
    • thread에게 할당된 자원이 모두 회수 되지 않을 가능성이 생긴다.
  • 지연 취소(defered cancellation)
    • 종료 신호를 보내면, 종료신호를 받은 thread는 적당한 때에 종료신호를 확인하고 자원을 잘 반납하고 종료한다.
    • 이 경우 어느정도 안전하다.
    • 내가 자주 사용하는 방식이다.

thread pools

  • 프로세스를 시작 할 때 아예 일정한 thread를 만들어둔다.
    • 그럼 생성했다가 삭제했다가 할 때 생기는 오버헤드를 줄일 수 있다.
    • 생성을 요청하면 대기하던 thread를 할당해주면 되니까

Leave a Comment