프로그래밍2008. 4. 28. 21:13
반응형


2. 기본 쓰레드 함수

주로 쓰레드 생성과 종료에 관련된 가장 기본적인 함수들이다.


2.1. pthread_create

int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
                   void *(*start_routine)(void *), void *arg);
			
쓰레드 생성을 위해서 사용한다. 첫번째 아규먼트인 thread 는 쓰레드가 성공적으로 생성되었을때 생성된 쓰레드를 식별하기 위해서 사용되는 쓰레드 식별자이다. 두번째 아규먼트인 attr 은 쓰레드 특성을 지정하기 위해서 사용하며, 기본 쓰레드 특성을 이용하고자 할경우에 NULL 을 사용한다. 3번째 아규먼트인 start_routine는 분기시켜서 실행할 쓰레드 함수이며, 4번째 아규먼는인 arg는 쓰레드 함수의 인자이다.

성공적으로 생성될경우 0을 리턴한다.

예제 : pthread_create.cc

#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

// 쓰레드 함수
void *t_function(void *data)
{
    int id;
    int i = 0;
    id = *((int *)data);

    while(1)
    {
        printf("%d : %d\n", id, i);
        i++;
        sleep(1);
    }
}

int main()
{
    pthread_t p_thread[2];
    int thr_id;
    int status;
    int a = 1;
    int b = 2;

    // 쓰레드 생성 아규먼트로 1 을 넘긴다.  
    thr_id = pthread_create(&p_thread[0], NULL, t_function, (void *)&a);
    if (thr_id < 0)
    {
        perror("thread create error : ");
        exit(0);
    }

    // 쓰레드 생성 아규먼트로 2 를 넘긴다. 
    thr_id = pthread_create(&p_thread[1], NULL, t_function, (void *)&b);
    if (thr_id < 0)
    {
        perror("thread create error : ");
        exit(0);
    }

    // 쓰레드 종료를 기다린다. 
    pthread_join(p_thread[0], (void **)&status);
    pthread_join(p_thread[1], (void **)&status);

    return 0;
}
			
실행된 쓰레드에 대해서는 pthread_join 등의 함수를 이용해서 쓰레드 종료때까지 기다려줘야 한다. ptherad_join 은 일종의 fork 의 wait 와 비슷하게 작동하며, 쓰레드자원을 해제 시켜준다.


2.2. pthread_join

#include <pthread.h>
int pthread_join(pthread_t th, void **thread_return);
			
첫번째 아규먼트 th기다릴(join)할 쓰레드 식별자이며, 두번째 아규먼트 thread_return은 쓰레드의 리턴(return) 값이다. thread_return 이 NULL 이 아닐경우 해다 포인터로 쓰레드 리턴 값을 받아올수 있다.

pthread_joinc.c

#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

// 쓰레드 함수 
// 1초를 기다린후 아규먼트^2 을 리턴한다. 
void *t_function(void *data)
{
    int num = *((int *)data);
    printf("num %d\n", num);
    sleep(1);
    return (void *)(num*num);
}

int main()
{
    pthread_t p_thread;
    int thr_id;
    int status;
    int a = 100;

    thr_id = pthread_create(&p_thread, NULL, t_function, (void *)&a);
    if (thr_id < 0)
    {
        perror("thread create error : ");
        exit(0);
    }
    // 쓰레드 식별자 p_thread 가 종료되길 기다렸다가 
    // 종료리턴값을 가져온다. 
    pthread_join(p_thread, (void *)&status);
    printf("thread join : %d\n", status);

    return 0;
}
			


2.3. pthread_detach

int pthread_detach(pthread_t th);
			
detach 는 "떼어내다" 라는 뜻을 가지며 main 쓰레드에서 pthread_create 를 이용해 생성된 쓰레드를 분리시킨다. 이 함수는 식별번호th인 쓰레드를 detach 시키는데, detach 되었을경우 해당(detach 된) 쓰레드가 종료될경우 pthread_joinc 을 호출하지 않더라도 즉시 모든 자원이 해제(free) 된다.

여기에서는 pthread_create 호출후 detach 하는 방법을 설명하고 있는데, pthread_create 호출시에 쓰레드가 detach 되도록 할수도 있다. 이에 대한 내용은 pthread_attr_setdetachstate 를 다루면서 설명하도록 하겠다.

예제 : pthread_detach.c

#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

// 쓰레드 함수
// 1초를 기다린후 아규먼트^2 을 리턴한다.
void *t_function(void *data)
{
    char a[100000];
    int num = *((int *)data);
	printf("Thread Start\n");
    sleep(5);
	printf("Thread end\n");
}

int main()
{
    pthread_t p_thread;
    int thr_id;
    int status;
    int a = 100;

	printf("Before Thread\n"); 
    thr_id = pthread_create(&p_thread, NULL, t_function, (void *)&a);
    if (thr_id < 0)
    {
        perror("thread create error : ");
        exit(0);
    }
    // 식별번호 p_thread 를 가지는 쓰레드를 detach 
    // 시켜준다. 
    pthread_detach(p_thread);
    pause();
    return 0;
}
			
위의 쏘쓰 코드에서 detach 시켰을때와 그렇지 않았을때의 메모리 상황을 비교해보기 바란다. detatach 를 했을경우 프로세스의 메모리 사용율과 detache 를 주석 처리했을경우의 메모리 사용율의 변화를 서로 비교해보면 되는데, detach 를 사용하지 않았을경우 t_function 이 종료가 되더라도 자원이 해제되지 않음을 볼수 있을것이다. 테스트는 간단한 스크립트를 이용하도록 한다.
[root@localhost test]# while [ 1 ]; do ps -aux | grep pthread | grep -v grep | grep -v vim; sleep 1; done
root      2668  0.0  0.1  1436  292 pts/8    S    18:37   0:00 ./pthread_detach
root      2668  0.0  0.1  1436  292 pts/8    S    18:37   0:00 ./pthread_detach
			
위의 ps 내용에서 5번째 필드의 변화를 확인하면 된다.


2.4. pthread_exit

void pthread_exit(void *retval);
			
pthread_exit 는 현재 실행중인 쓰레드를 종료시키고자 할때 사용한다. 만약 pthread_cleanup_push 가 정의되어 있다면, pthread_exit 가 호출될경우 cleanup handler 가 호출된다. 보통 이 cleanup handler 은 메모리를 정리하는 등의 일을 하게 된다.

예제 : pthread_exit.c

#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

// 쓰레드 함수
// 1초를 기다린후 아규먼트^2 을 리턴한다.
void *t_function(void *data)
{
    int num = *((int *)data);
    int i = 0;
    while(1)
    {
        if (i == 3)
            pthread_exit(0);
        printf("loop %d\n", i);
        i++;
        sleep(1);
    }
}

int main()
{
    pthread_t p_thread;
    int thr_id;
    int status;
    int a = 100;


    thr_id = pthread_create(&p_thread, NULL, t_function, (void *)&a);
    if (thr_id < 0)
    {
        perror("thread create error : ");
        exit(0);
    }
    pthread_join(p_thread, (void **)&status);
    return 0;
}
			


2.5. pthread_cleanup_push

void pthrad_cleanup_push(void (*routine) (void *), void *arg);
			
이것은 cleanup handlers 를 인스톨하기 위해서 사용된다. pthread_exit(3) 가 호출되어서 쓰레드가 종료될때 pthread_cleanup_push 에 의해서 인스톨된 함수가 호출된다. routine이 쓰레드가 종료될때 호출되는 함수이다. arg는 아규먼트이다.

cleanup handlers 는 주로 자원을 되돌려주거나, mutex 잠금등의 해제를 위한 용도로 사용된다. 만약 mutex 영역에서 pthread_exit 가 호출되어 버릴경우 다른쓰레드에서 영원히 block 될수 있기 때문이다. 또한 malloc 으로 할당받은 메모리, 열린 파일지정자를 닫기 위해서도 사용한다.

예제 : pthread_cleanup.c

#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>

// 쓰레드 함수
// 1초를 기다린후 아규먼트^2 을 리턴한다.
//

char *mydata;
void cleanup(void *);
void *t_function(void *data)
{
    int num = *((int *)data);
    int i = 0;
    int a = 1;
    // cleanup handler 로 cleanup 함수를 
    // 지정한다. 
    pthread_cleanup_push(cleanup, (void *)&a);
    mydata = (char *)malloc(1000);
    while(1)
    {
        if (i == 3)
        {
            // pthread_exit 가 호출되면서 
            // cleanup 을 호출하게 된다. 
            pthread_exit(0);
            return 1;
        }
        printf("loop %d\n", i);
        i++;
        sleep(1);
    }
    pthread_cleanup_pop(0);
}


int main()
{
    pthread_t p_thread;
    int thr_id;
    int status;
    int a = 100;


    thr_id = pthread_create(&p_thread, NULL, t_function, (void *)&a);
    if (thr_id < 0)
    {
        perror("thread create error : ");
        exit(0);
    }
    pthread_join(p_thread, (void **)&status);
    printf("Join finish\n");
}

// cleanup handler
void cleanup(void *myarg)
{
    printf("thread is clean up\n");
    printf("resource free\n");
    free(mydata);
}
			


2.6. pthread_cleanup_pop

pthread_cleanup_push 와 함께 사용되며, install 된 cleanup handler 을 제거하기 위해서 사용된다.

void pthread_cleanup_pop(int execute);
			
만약 execute 가 0 이라면, pthread_cleanup_push 에 의해 인스톨된 cleanup handler 를 (실행시키지 않고)삭제만 시킨다. 0 이 아닌 숫자라면 cleanup handler 을 실행시키고 삭제 된다. 사용예제는 2.5절을 참고하라.

그리고 pthread_cleanup_push 와 pthread_cleanup_pop 은 반드시 같은 함수내의 같은 레벨의 블럭에서 한쌍으로 사용해야 한다.


2.7. pthread_self

pthread_t pthread_self(void);
			
pthread_self를 호출하는 현재 쓰래드의 쓰레드식별자를 되돌려준다.

예제 : pthread_self.c

#include <pthread.h>
#include <stdio.h>

void *func(void *a)
{
    pthread_t id;
    id = pthread_self();
    printf("->%d\n", id);
}

int main(int argc, char **argv)
{
    pthread_t p_thread;
    pthread_create(&p_thread, NULL, func, (void *)NULL);
    printf("%d\n", p_thread);
    pthread_create(&p_thread, NULL, func, (void *)NULL);
    printf("%d\n", p_thread);

	return 1;
}


출처 : http://www.joinc.co.kr/modules/moniwiki/wiki.php/article/Pthread_API_Reference


반응형

'프로그래밍' 카테고리의 다른 글

리눅스에서 fflush() 안 될때 해결책  (0) 2009.04.23
쓰레드 동기화 함수  (0) 2008.04.28
fork와 thread의 차이점  (0) 2008.04.28
간단한 thread 함수 예제  (0) 2008.04.28
이진 탐색 트리  (0) 2008.04.28
Posted by pmj0403