Shine's dev log

쓰레드(Thread)_3 (Issues in Threading) 본문

운영체제

쓰레드(Thread)_3 (Issues in Threading)

dong1 2020. 4. 28. 14:53

쓰레드를 이용하다보면 생길법한 Issues 들에 대하여 한번 살펴보자.

 

 

1. fork() 와 exec()

 

만약 프로세스에 여러개의 쓰레드가 실행중일 때, exec()를 만나면 어떻게될까? 답은 간단하다. 현재 프로세스에 몇개의 쓰레드가 있던간에 그냥 싹 다 밀어버리고, 새로운 프로그램을 하나의 쓰레드로 실행시킨다.

 

그렇다면 여러개의 쓰레드가 실행중일때, 하나의 쓰레드가 fork()를 만나면 어떻게 될까? 이는 운영체제마다 조금씩 다른데, Pthread에서는 fork()를 부른 쓰레드만 남긴다. 하지만 일부 UNIX International standard에서는 실행중인 모든 쓰레드를 그대로 복사하는 경우도 지원한다.

 

 

 

2. signal Handling

 

다음으로 만약 멀티쓰레딩 프로세스에 signal이 들어온다면 어떻게 처리해야할까?

 

(참고로 프로세스내의 쓰레드들끼리는 signal handler를 공유한다.)

 

이럴 경우에는 여러가지 케이스들이 있을 것인데, 하나씩 살펴보자.

 

1) 그 signal을 발생시킨 장본인이 signal을 처리.

 

0으로 나누거나 잘못된 address를 참조하는 등의 synchronous signals가 발생했을 경우

 

2) 그 프로세스내의 모든 쓰레드들에게 broadcasting해주고, 그중에 적절한 쓰레드가 처리하는식으로 처리.

 

외부에서 프로세스에게 assynchronous signal을 발생시킨 경우.

 

3) 미리 signal을 처리할 쓰레드를 정해놓고 그 쓰레드가 전담해서 signal 처리

 

signal mask를 이용하면 나머지 쓰레드는 signal을 무시할 수 있으므로, 특정 signal만 maks를 풀어주면 전담처리 가능하다.

 

 

 

3. Thread Cancellation

 

멀티 쓰레딩 프로세스에서 쓰레드를 죽이고 싶을때는 어떤 issues 들이 있을지 살펴보자.

 

1) Asynchronous cancellation

 

쓰레드가 동작하다가 다른애가 "죽어!" 해서 묻지도 따지지도 않고 죽어버리는 경우로, 만약 죽는 쓰레드가 resource를 가지고 있었다면 문제가 생길 여지가 있다.

 

2) Deferred cancellation

 

누군가 죽여도 바로 죽는게 아니라 cancellation point 라는 곳에서만 죽는 방법이다. 각 포인트마다 과연 이 쓰레드가 죽어도 되는지 체크하기 때문에 resource 관련 문제가 어느정도 해결된다.

 

참고로 Pthread API는 둘 다 지원해준다.

 

 

 

4. Thread-Local Storage (TLS)

 

TLS는 한마디로 말하면, "Scope가 Thread인 global Variable" 이다.

 

크게 두가지 경우에서 요긴하게 사용된다.

 

1) Synchronization 하는 경우

 

각 쓰레드마다 쓰이는 변수가 있으므로, 여러쓰레드에서 동시에 같은 변수에 접근하여 발생하는 오류를 줄일 수 있다.

 

2) Error handling

 

쓰레드마다 다른 파일을 read할 때, errno가 각각 다를 것인데, 만약 global variable 쓰면, 에러메시지가 제대로 안나오고 중첩되버리는데, 이럴 경우 TLS를 쓰면 매우 요긴하다.

 

 

 

5. Threads in Linux

 

사실 리눅스에는 프로세스가 없다!

 

이게 무슨 소리냐고 생각할 수도 있지만, 리눅스에서는 쓰레드를 task로 처리하고, 만약 task들끼리 가리키는 address space가 같으면 그 task들을 하나의 프로세스로 추상화한다.

 

리눅스에서는 clone() 시스템콜을 이용하여 task를 생산한다.

 

Threads in Linux

 

이러한 특징때문에 memory space, file system, signal handle을 task마다 공유할지 말지 설정할 수 있다.

 

 

 

오늘 내용을 정리해보면.

 

1. 쓰레드를 사용할때 여러가지 이슈들이 있다.

 

2. fork(), exec(), cancellation, signal handling, TLS 등의 이슈들은 정해진 기준에 따라 처리된다.

 

3. 리눅스는 쓰레드를 task로 추상화하여 처리한다.

 

 

본 내용은 공부하며 정리한 것으로, 오류가 있을 수 있습니다.