열렬히.뛰기

쓰레드 관련 문제

운영체제 > Part 2 : 프로세스 관리 > 공룡책 4장 : 쓰레드 > 쓰레드 관련 문제

다중 쓰레드 프로그램 설계 시 고려해야 할 몇 가지 점을 알아보자.

fork()와 exec() 시스템 콜

만약 한 프로그램의 쓰레드가 fork()를 호출한다면

  • 새 프로세스는 모든 쓰레드를 복제해야 하는가?
  • 아님 한 개의 쓰레드만을 가져야 하는 프로세스여야 하는가?

몇몇 유닉스는 이 두 모드를 동시에 지원한다. 이를 선택하는 것은 결국 App 설계자의 몫.

exec()의 경우 모든 쓰레드를 포함한 전체 프로세스를 대체한다.

신호처리

신호의 정의와 처리

💡 신호 = 프로세스에 어떠한 이벤트가 일어났음을 알려주기 위해 사용됨.

모든 신호는 다음과 같은 형태로 전달된다.

  1. 신호는 특정 이벤트가 일어나야 생성된다.
  2. 생성된 신호가 프로세스에 전달된다.
  3. 신호가 전달되면 반드시 처리해야 한다.

동기식 신호 : 실행 중인 프로세스 내부에서 발생한 신호

  • 예시 : 불법적 메모리 접근, 0으로 나누기
  • 신호를 발생시킨 연산을 수행한 동일한 프로세스에만 전달

비동기식 신호: 실행 중인 프로세스 외부에서 발생한 신호

  • 예시 : ctrl + c, 타이머 만료

모든 신호는 둘 중 하나에 의해 처리된다.

  1. 디폴트 신호 처리기
  2. 사용자 정의 신호 처리기

신호처리와 쓰레드

단일 쓰레드 : 신호는 항상 프로세스에 전달

다중 쓰레드 : 여러가지 경로가 존재.

  1. 신호가 적용될 쓰레드에 전달
  2. 모든 쓰레드에 전달
  3. 몇몇 쓰레드에 선택적 전달
  4. 특정 쓰레드가 모든 신호를 받는다.

비동기식 신호의 경우에는 특히 이러한 선택지가 원할하지 않다.

  • kill() 의 경우 특정 신호가 전달될 프로세스를 지정

  • 대부분의 다중 쓰레드 지원 유닉스는 받아드릴 신호와

    봉쇄할 신호를 지정할 선택권을 부여한다.

쓰레드 취소

쓰레드 강제종료를 의미한다. 이때의 쓰레드를 목적 쓰레드라고 한다.

목적 쓰레드의 취소는 2가지 방식으로 발생시킬 수 있다.

  1. 비동기식 취소 : 한 쓰레드가 즉시 목적 쓰레드를 강제 종료
  2. 지연 취소 : 목적 쓰레드가 주기적으로 자신이 종료대상인지 점검.

쓰레드 취소를 어렵게 하는 것은 취소 쓰레드에 할당된 자원 문제.

또 쓰레드가 타 쓰레드와 자원을 공유하는 상황에서 취소 요청이 와도 문제.

  • 따라서 비동기식 취소는 필요한 자원을 다 회수하지 못 할 수도 있다.
  • 그래서 기본적인 유형은 지원 취소이다.

쓰레드-로컬 저장장치

각각의 쓰레드만 접근할 수 있는 데이터가 필요하기도 하다.

이를 저장하는 곳은 쓰레드-로컬 저장장치 (TLS)라고 한다.

중요한 점은 TLS와 지역변수가 다르다는 것!

  • 지역변수 : 하나의 함수에 국한.
  • TLS : 전체 함수 호출에 걸쳐 보인다.

정적 데이터(static)과 좀 더 유사.

스케쥴러 액티베이션

쓰레드 라이브러리와 커널의 통신 문제도 고려해야 한다.

  • 특히 다대다 또는 2수준 모델에서 더 중요하다.
  • 얼마나 많은 커널 쓰레드가 필요한지 파악 후 조절

이 경우, 사용자 쓰레드와 커널 쓰레드 사이에 중간 자료구조를 둔다.

  • 이를 경량 프로세스(LWP) 라고 한다.

  • 프로그램의 효율적 실행을 위해 LWP의 갯수를 조정해야 할 수도 있다.

  • 사용자 스레드 라이브러리에게 있어, LWP은 응용이 사용자 스레드를 스케줄할 수 있는 가상 처리기처럼 보인다.

    커널은 관여하지 않는 것처럼 보인다.

  • LWP는 하나의 커널 스레드에 부속되어 있으며, 사용자 스레드와도 연결되어 있다.

  • 물리 처리기에서 스케줄 하는 대상은 커널 스레드이다.

  • 커널 스레드가 입출력같은 것을 동기식으로 기다리면 LWP가 기다리고, 이에 연결된 사용자 스레드도 기다린다.

사용자 스레드 라이브러리와 커널 스레드 간의 통신 방법 중 하나는 스케줄러 액티베이션이다.

  • 커널은 응용 프로그램에게 가상 처리기 집합(LWP)을 제공한다.
  • 응용 프로그램을 이를 통해 사용자 스레드를 스케줄 한다.

커널은 upcall 이라 불리는 프로시저를 통하여 응용 프로그램에게 사건을 알린다.

  • 사건은 응용 프로그램의 스레드가 봉쇄(동기)하려고 할 때 발생한다.
  • upcall은 가상 처리기에서 수행되는, 스레드 라이브러리의 upcall 처리기에 의해 처리된다.

upcall 처리는 다음과 같이 수행된다.

  1. 커널이 스레드가 봉쇄하려고 하는 것과 스레드의 식별자를 알려주는 upcall을 한다.
  2. 커널이 새로운 가상 처리기를 응용 프로그램에게 할당한다.
  3. 응용 프로그램이 새로운 가상 처리기에서 upcall 처리기를 수행한다.
  4. upcall 처리기는 봉쇄 스레드의 상태를 저장하고 원래 가상 처리기를 반환한다.
  5. upcall 처리기는 새로운 가상 처리기에서 응용 프로그램의 실행 가능한 스레드를 스케줄 한다.
  6. 커널이 봉쇄가 풀리는 사건을 감지하고 upcall을 스레드 라이브러리에게 한다.