pthread 관련 함수 및 취소 요청

pthread 함수

pthread에 관한 예제의 경우 대부분 pthread_join()을 통해 쓰레드의 종료를 기다린 후 메인 루프가 종료되는 형식입니다.

백그라운드로 다른 프로그램을 실행하거나 동적으로 라이브러리를 링크하여 사용할 경우 상황에 따라 쓰레드가 끝나는 것을 기다리지 않고,

메인 프로그램을 종료해야할 경우도 있습니다.

이번 포스팅에서는 쓰레드의 취소나 종료의 관점에서 동작과 필요 함수들을 다뤄보겠습니다.

 

멀티 쓰레드 프로그램은 쓰레드간 동기화를 위해서 조건변수, 뮤텍스 등을 사용할 수도 있고 여러가지 공유 자원들을 가지고 있을 수 있습니다.

공유 자원에 대한 접근이나 사용은 항시 주의해야 합니다.

 

pthread_create

함수 원형: int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine)(void *), void *arg);
해당 함수는 쓰레드를 생성하기 위해서 사용합니다. 

- 첫번째 인자 thread는 쓰레드가 성공적으로 생성되었을때 생성된 쓰레드를 식별하기 위해서 사용되는 쓰레드 식별자 
- 두번째 인자 attr은 쓰레드 특성을 지정하기 위해서 사용하며, 기본 쓰레드 특성을 이용하고자 할 경우에 NULL을 사용
- 세번째 인자 start_routine는 분기시켜서 실행할 쓰레드 함수 
- 네번째 인자 arg는 쓰레드 함수의 인자

 

pthread_cancel

함수 원형: int pthread_cancel(pthread_t thread);
해당 함수는 인자로 주어진 쓰레드 식별번호 thread를 가지는 쓰레드를 중지시킵니다. 
엄밀히 말하자면 쓰레드를 중지 시키는 것이 아니라 취소 요청을 보내는 것인데, 취소 요청은 취소 상태와 취소 종류 두 가지로 나뉩니다. 

 

pthread_attr_init

함수 원형: int pthread_attr_init(pthread_attr_t *attr);    
해당 함수는 thread attribute 객체인 attr을 default 값으로 초기화 시킵니다.

 

pthread_attr_distroy

함수 원형: int pthread_attr_destroy(pthread_attr_t *attr);    
해당 함수는 pthread_attr_init에 의해 생성된 thread attribute 객체인 attr을 제거합니다. 
제거한 attr을 객체를 다시 사용하기 위해서는 pthread_attr_init를 사용하여 다시 초기화 해주는 작업이 필요합니다.

 

pthread_attr_setdetachstate

함수 원형: int  pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate);
쓰레드의 상태를 PTHREAD_CREATE_JOINABLE 혹은 PTHREAD_CREATE_DETACHED 상태로 변경시키기 위해서 사용됩니다.

두 가지의 옵션을 주는 방법이 있습니다.

- JOINABLE 상태로 변경: Default 값이고 join이 가능한 상태
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); 
- DETACHED 상태로 변경: 해당 쓰레드가 독립적으로 실행되도록 설정한 상태
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 

 

쓰레드 취소 상태의 설정

취소 상태는 pthread_setcancelstate() 함수에 의해 결정됩니다.
쓰레드는 PTHREAD_CANCEL_DISABLE와 PTHREAD_CANCEL_ENABLE 중에 하나의 취소 상태를 설정할 수 있습니다.

첫번째 인자인 state는 새로운 취소 상태를 설정하기 위해서 사용하고,

두번째 인자인 oldstate는 이전의 취소 상태의 설정 값을 받아오기 위해 사용합니다.

이전 취소 상태의 설정 값이 필요없다면  NULL을 사용하면 됩니다.

- PTHREAD_CANCEL_ENABLE 상태라면 쓰레드는 취소요청을 받아들이고 취소지점까지 진행한 다음 취소 지점을 벗어난 후 종료합니다.

- PTHREAD_CANCEL_DISABLE 상태라면 취소요청을 받아도 쓰레드가 종료되지 않습니다.

 

쓰레드 취소 종류의 설정

쓰레드 취소 상태가 PTHREAD_CANCEL_ENABLE일 경우 취소의 종류를 결정할 수 있습니다. 
취소 종류의 결정은 pthread_setcanceltype() 함수에 의해 결정됩니다.

첫번째 인자인 type 새로운 취소 종류를 설정하기 위해서 사용하고,

두번째 인자인 oldtype은 이전의 취소 종류의 설정 값을 받아오기 위해 사용합니다.

이전 취소 종류의 설정 값이 필요없다면  NULL을 사용하면 됩니다.

- PTHREAD_CANCEL_ASYNCHRONOUS 설정의 경우 쓰레드가 바로 종료됩니다. 
- PTHREAD_CANCEL_DEFERRED 설정의 경우 취소 지점을 벗어날 때까지 기다립니다. 

 

pthread 취소 요청 예제

Main Loop에서 Thread를 독립적으로 생성, 10초 후 쓰레드에게 취소를 요청하는 예제입니다.

쓰레드에 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL)의 취소 상태로 요청을 받아들이고,

pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS,NULL)의 취소 종료를 선언함으로써

쓰레드가 바로 종료되도록 설정하였습니다.

Qt 환경에서 undefineundefined reference to 'pthread_create' Error 발생 시 .pro 파일에 아래의 코드를 추가합니다.

QMAKE_CXXFLAGS += -std=c++0x -pthread

LIBS += -pthread

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#include <iostream>
#include <pthread.h>
#include <unistd.h>
 
using namespace std;
 
pthread_t t_thread;
void *ThreadTest(void *arg);
 
int main(int argc, char *argv[])
{
    int status = 0;
    int arg = 0;
    pthread_attr_t attr;
 
    pthread_attr_init(&attr);
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
    status = pthread_create(&t_thread, &attr, ThreadTest, &arg);
    pthread_attr_destroy(&attr);
 
    sleep(10);
    pthread_cancel(t_thread);
    cout << "pthread cancel" << endl;
 
    return 0;
}
 
void *ThreadTest(void *arg)
{
    pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
    pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS,NULL);
 
    while(1)
    {
        sleep(1);
        cout << "pthread" << endl;
    }
}