본문 바로가기

프로그래밍/C

[function] pthread_create 함수 알아보기

📌 매뉴얼 (Linux)

더보기

NAME

      pthread_create - create a new thread

 

SYNOPSIS

       #include <pthread.h>

       int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg);

       Compile and link with -pthread.

 

DESCRIPTION

       The pthread_create() function starts a new thread in the calling process.

       The new thread starts execution by invoking start_routine(); arg is passed as the sole argument of

       start_routine(). The new thread terminates in one of the following ways: * It calls pthread_exit(3),

       specifying an exit status value that is available to another thread in the same process that calls

       pthread_join(3). * It returns from start_routine(). This is equivalent to calling pthread_exit(3) with

       the value supplied in the return statement. * It is canceled (see pthread_cancel(3)).

       * Any of the threads in the process calls exit(3), or the main thread performs a return from main().

       This causes the termination of all threads in the process. The attr argument points to a pthread_attr_t

       structure whose contents are used at thread creation time to de‐ termine attributes for the new thread;

       this structure is initialized using pthread_attr_init(3) and related functions. If attr is NULL, then the thread

       is created with default attributes. Before returning, a successful call to pthread_create() stores the ID

       of the new thread in the buffer pointed to by thread; this identifier is used to refer to the thread in

       subsequent calls to other pthreads functions. The new thread inherits a copy of the creating thread's

       signal mask (pthread_sigmask(3)). The set of pending signals for the new thread is empty (sigpending(2)).

       The new thread does not inherit the creating thread's alternate signal stack (sigaltstack(2)).

       The new thread inherits the calling thread's floating-point environment (fenv(3)).

       The initial value of the new thread's CPU-time clock is 0 (see pthread_getcpuclockid(3)).

Linux-specific details

       The new thread inherits copies of the calling thread's capability sets (see capabilities(7)) and

       CPU affinity mask (see sched_setaffinity(2)).

 

RETURN VALUE

       On success, pthread_create() returns 0;

       on error, it returns an error number, and the contents of *thread are undefined.

 

📌 함수 설명

우선, pthread란, POSIX Thread의 약자로, 유닉스 계열 운영체제에서 thread를 만들 수 있게 하는 API이다.

pthread.h 를 include 해서 사용할 수 있으며, pthread_create를 통해 thread를 생성할 수 있다.

pthread_create 함수는 호출 시 해당 프로세스에서 새 스레드를 생성하고, 인자로 받은 start_routine 함수를 실행한다.

 

int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg);

함수의 매개변수로 4개의 인자가 들어오는데 각각 살펴보자.

 

pthread_t *thread : 생성된 스레드의 ID를 저장할 스레드 식별자. 

이 인자 값을 통해서 pthread_join과 같은 함수들을 사용한다.

const pthread_attr_t *attr : 설정할 스레드의 특성 및 속성 정보 (NULL 입력시 기본설정)

속성을 지정하려고 한다면 pthread_attr_init 등의 함수로 초기화한다.

void *(*start_routine) (void *) : 스레드가 실행할 함수의 포인터 (스레드 생성 시 실행된다.)

void *arg : start_routine 함수에 전달하고자 하는 인자 값


단순하게, pthread_create 함수만을 이용해서 thread를 하나 생성해 함수 하나를 실행하는 것을 살펴보도록 하겠다.

 

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

void    *thread_func(void *arg)
{
    int i = 0;
    int c = *((int*) arg);
    
    while(i < c)
    {
        sleep(1);
        printf("running thread %d\n", i);
        i ++;
    }
    return (NULL);
}

int main(void)
{
    pthread_t   thread_ID;
    int         arg = 5;

    if(pthread_create(&thread_ID, NULL, thread_func, (void *)&arg) != 0)
        exit(1);
    sleep(10);
    printf("end\n");
    return (0);
}

 

출력 - std_output)

 

위의 코드는 main에서 pthread_create 함수를 사용하여 thread_func 라는 함수를 실행케하는 스레드 하나를 만들 것이다.

이를 하나씩 확인해보면, 우선 pthread_create의 첫 매개변수로 들어갈 pthread_t 로 선언되는 thread_ID를 만든다.

이는 스레드 식별자로, 추후에 스레드를 특정하여 식별할 때 사용된다.

그리고, 매개변수로 쓸 arg를 하나 만들고 이를 4번째 매개변수에 void *로 캐스팅해 넣어준다.

 

스레드가 생성에 성공하면 0을 반환하므로, 0이 아닐 때는 오류로 exit(1)을 해주었고,

함수가 실행되면 위처럼 thread_func을 실행한 output이 실행된다.

main도 하나의 스레드이므로, main 스레드가 종료되버리면 프로세스 자체가 끝나버리기 때문에,

우리가 만든 스레드가 종료된 이후에 main이 종료되도록 sleep을 10 정도로 따로 걸어뒀다.

 

위 코드를 통해서 pthread_create로 하나의 스레드를 만들어보았다.


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

void    *thread_func(void *arg)
{
    int i = *((int*) arg);
    int c = *((int*) arg) + 5;
    
    while(i <= c)
    {
        sleep(1);
        printf("running thread %d\n", i);
        i ++;
    }
    return (NULL);
}

int main(void)
{
    pthread_t   thread_ID1;
    pthread_t   thread_ID2;
    int         arg1 = 0;
    int         arg2 = 5;

    if(pthread_create(&thread_ID1, NULL, thread_func, (void *)&arg1) != 0)
        exit(1);
    if(pthread_create(&thread_ID2, NULL, thread_func, (void *)&arg2) != 0)
        exit(1);
    sleep(10);
    printf("ID1 : %ld, ID2 : %ld\n", thread_ID1, thread_ID2);
    return (0);
}

 

출력 - std_output)

 

그렇다면, 이번에는 두개의 스레드를 한번 만들어보도록 하겠다.

각각 다른 ID변수에 스레드 식별자를 저장해줬고, 다른 ID를 가짐을 print하여 확인해보았다.

두 스레드는 동시에 실행되며, 마찬가지로 main 스레드는 기다리게 sleep을 걸어줬다.

실행결과를 통해, main 스레드 + ID1을 가지는 스레드 + ID2를 가지는 스레드

세 개의 스레드가 동시에 진행되는 것을 볼 수 있다.

 

생성한 두 스레드의 순서는 먼저 만든 스레드가 먼저 실행되는 것을 볼 수 있다.

이는 스레드 스케줄링에 의해 우선순위가 먼저 만든 스레드에 부여된 것으로 보인다.

(스레드 스케줄링 : 어떤 순서에 의해 스레드가 번갈아가며 실행될 것인지에 대한 결정 방식)


이렇게 pthread_create 함수에 대해 간단한 예시를 통해서 알아보았다.

이후에 사용할 pthread 관련 함수들을 이용하기 전 스레드를 생성하는 가장 기본이 되는 함수였고,

앞으로 어떤 pthread 함수들을 알아볼 때 우선적으로 사용될 것이다.

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

[function] pthread_detach 함수 알아보기  (2) 2024.09.18
[function] pthread_join 함수 알아보기  (8) 2024.09.07
[utility] get_next_line 구현하기  (3) 2024.08.31
[graphic] miniLibX Manual  (0) 2024.08.06
[library] itoa 구현하기  (0) 2024.06.29
Recent Posts
Popular Posts
Recent Comments