본문 바로가기
반도체 그 다음 학문/운영체제 (OS)

운영체제 Thread Libraries, Threading issues ( Pthread, Implicit Threading, Tread pools, openMP, fork-join )

by 전컴반 2022. 4. 13.
반응형
Thread Libraries

 

- Thread Libraries는 프로그래머에게 thread를 관리하고 생성하는 API를 제공해주는 것이다.  구현에는 2가지 방식이 있다.

1. user space에서의 구현

2. kernel level에서의 구현

 

user space에서 구현을 하게 되면 시스템 콜의 형태가 아닌 user space에서 지역 함수를 호출하게 된다는 특징이 있다

kernel level에서 구현한다면 시스템 콜을 호출하는 것과 똑같이 된다.

 

Pthread

 

- A POSIX가 재정한 API의 생성과 동기화의 표준화이다. 표준화이지 어떤 구현에 관한 것은 아니다.

 

가령 10개의 threads를 join 하는 코드는 아래와 같다.

 

#define NUM_THREADS 10

pthread_t workers [NUM_THREADS];

for (int i = 0 ; i < NUM_THREADS; i++)
    pthread_join(worker[i], NULL);

 

 

Implicit Threading

 

- Implicit Threading은 thread의 생성과 관리 책임을 컴파일러와 런타임 라이브러리가 하는 것이다. 앞전에 설명했던 관리 방법은 (ex, one to one, many to many..) explicit threading이라고 볼 수 있다. 즉, 지정에 의해 동작했다.

 

개발자는 병렬로 실행할 수 있는 작업만 식별하여 작업을 함수로 작성한다. 이후 런타임 라이브러리를 통해 가용한 스레드에 매핑된다. 결국 스레드 생성과 관리는 시스템이 하고 애플리케이션에서는 라이브러리를 통해 스레드에 필요한 작업을 맵핑만 하면 된다. 예로는 thread pools, openMP, fork-join과 같은 것들이 있다.

 

 

1. Tread pools

- 프로세서를 시작할 때 thread를 일정 숫자에 맞게 미리 생성해 놓는 방법이다. 새로 생성해서 쓰는 것보다 더 빠른 서비스를 제공할 수 있다. 또한 API를 제공해줘서 사용하기에도 편하다. 

 

2. openMP

- 스레딩을 language 수준에서 미리 기술하는 방법이다. parallel regions를 미리 정하는 형태로 동작하는데, 주로 #progma 코드를 이용하여 parallel regions를 정의해준다.

 

3. fork-join

- 메인 스레드가 여러 개의 자식 스레드들을 만들고(fork) 자식 스레드들이 일을 마치고 다시 합쳐지는(join) 형태이다.

 

 

Threading issues

 

- Threading 할 때 생기는 문제에 대해 알아보자.

 

1. 시스템 콜에서 fork(), exec()의 의미 

- 다중 스레드 프로그램에서는 fork()와 exec() 시스템 호출의 의미가 달라질 수 있다.

한 프로그램의 스레드가 fork()를 호출하면, 새로운 프로세스는 모든 스레드를 복사 또는 fork() 시스템을 호출한 스레드만 복제한다.

 

Exec() 시스템을 호출하면, exec()의 매개변수로 지정된 프로그램이 전체 프로세스를 대체시킨다.

fork()를 부르자마자 다시 exec()을 부른다면 exec()에서 지정한 프로그램이 곧 모든 것을 다시 대체할 것이기 때문에 모든 스레드를 복제해서 만들어주는 것은 불필요하다.

Fork() 후 exec()를 하지 않는다면 새 프로세스는 모든 스레드들을 복제해야 한다.

 


2. 신호처리 (sinal handling)

- 신호는 프로세스에서 특정 이벤트의 발생을 알려준다. 신호 처리는 다음과 같이 전달된다.

 

첫 번째, 신호는 특정 사건이 일어나야 생성된다.

두 번째, 신호가 생성되면 프로세스에게 전달된다

세 번째. 신호가 전달되면 반드시 처리되어야 한다.

 

신호 발생은 동기식과 비동기식으로 전달 가능한데, 동기식 신호는 올바르지 않은 메모리의 접근에 대해 신호를 발생시킨다. 가령 0 나누기 같은 연산이 있다.

 

비동기식 신호는 외부로부터 발생되는 신호이며 <contorl><c> 같은 특수한 키를 눌러서 강제로 종료하거나 타이머의 만료를 포함한다. 또한 비동기식 신호는 다른 프로세서에게 전달된다.

 

그렇다면 뭐가 default일까?? kernel에 의해 실행되는데 이 신호를 무시 또는 강제 종료가 된다. 다중 스레스 프로그램에서의 처리는 4가지가 있다.

 

첫 번째, 신호가 적용될 스레스들에게 전달된다.

두 번째, 모든 스레드들에게 전달한다.

세 번째, 일부 스레드에게만 선택적으로 전달된다.

네 번째, 특정 스레드가 모든 신호를 전달받도록 지정한다.

 

동기식 신호는 문제를 야기한 스레드들에게 모두 전달돼야 하며 다른 스레드들에겐 전달하지 않는다. 하지만 비동기식 신호는 명확하지 않기 때문에 프로세스 내에 모든 스레드들에게 전달된다.

 

 

3. 취소 (cancellation)

- 스레드가 끝나기 전에 강제로 종료시키는 동작이다. 취소시켜야 할 스레드를 target thread라고 한다. 2가지 방법이 있는데

 

지연 취소는 target을 주기적으로 확인하며 강제 종료돼야 하는지 확인한다.

비동기식 취소는 즉시 target을 종료시킨다.

 

하지만 스레드의 자원 공유나 정보를 업데이트 중에 취소 요청이 왔다면 어떻게 해야 할까?

 

지연 취소는 target의 취소 여부는 플래그를 검사한 이후에 일어나는데 이때 target이 현재 취소되어도 문제가 없다고 판단되는 시점에서 취소 여부를 검사할 수 있다. 이때를 cacellation point라고 한다.

비동기 취소는 운영체제에서 취소된 스레드에서 자원을 회수하지 못하여 취소하지 못할 수도 있다.

반응형

댓글