NAME

pthread_attr_init, pthread_attr_destroy - 스레드 속성 객체 초기화 및 파기

SYNOPSIS

#include <pthread.h>

int pthread_attr_init(pthread_attr_t *attr);
int pthread_attr_destroy(pthread_attr_t *attr);

-pthread로 컴파일 및 링크.

DESCRIPTION

pthread_attr_init() 함수는 attr이 가리키는 스레드 속성 객체를 기본 속성 값들로 초기화 한다. 이 호출 다음에 (SEE ALSO에 나열된) 여러 관련 함수들을 써서 객체의 개별 속성을 설정할 수 있으며, 그러고 나서 그 객체를 스레드를 생성하는 pthread_create(3) 호출에 한 번 또는 그 이상 사용할 수 있다.

이미 초기화 된 스레드 속성 객체에 pthread_attr_init()을 호출하는 결과는 규정되어 있지 않다.

스레드 속성 객체가 더는 필요치 않으면 pthread_attr_destroy() 함수를 이용해 파기해야 한다. 스레드 속성 객체 파기는 그 객체로 생성된 스레드에 어떤 영향도 주지 않는다.

스레드 속성 객체를 파기하고 나면 pthread_attr_init()으로 다시 초기화 할 수 있다. 파기된 스레드 속성 객체를 그 외 어떤 방식으로든 쓰는 결과는 규정되어 있지 않다.

RETURN VALUE

성공 시 이 함수들은 0을 반환한다. 오류 시 0 아닌 오류 번호를 반환한다.

ERRORS

POSIX.1에서는 pthread_attr_init()ENOMEM 오류도 적고 있다. 리눅스에서는 이 함수들이 항상 성공한다. (그렇기는 하지만 이식 가능하고 미래를 대비하는 응용에서는 가능한 오류 반환을 처리해야 할 것이다.)

ATTRIBUTES

이 절에서 사용하는 용어들에 대한 설명은 attributes(7)를 보라.

인터페이스 속성
pthread_attr_init(), pthread_attr_destroy() 스레드 안전성 MT-Safe

CONFORMING TO

POSIX.1-2001, POSIX.1-2008.

NOTES

pthread_attr_t 타입을 불투명한 것으로 취급해야 한다. pthreads 함수를 통하지 않은 방식으로 객체에 접근하는 것은 이식성이 없으며 규정되지 않은 결과를 유발한다.

EXAMPLES

아래 프로그램에서는 선택적으로 pthread_attr_init()과 여러 관련 함수들을 이용해 스레드 속성 객체를 초기화하고 스레드 한 개를 생성한다. 생성된 스레드는 pthread_getattr_np(3) 함수(비표준 GNU 확장)로 스레드의 속성을 얻어 와서 그 속성들을 표시한다.

명령행 인자 없이 프로그램을 실행하면 pthread_create(3)attr 인자로 NULL을 전달하며, 그래서 기본 속성으로 스레드를 생성한다. NPTL 스레딩 구현이 있는 리눅스/x86-32에서 프로그램을 돌리면 다음과 같이 나온다.

$ ulimit -s       # 스택 제한 없음 ==> 기본 스택 크기 2MB
unlimited
$ ./a.out
Thread attributes:
        Detach state        = PTHREAD_CREATE_JOINABLE
        Scope               = PTHREAD_SCOPE_SYSTEM
        Inherit scheduler   = PTHREAD_INHERIT_SCHED
        Scheduling policy   = SCHED_OTHER
        Scheduling priority = 0
        Guard size          = 4096 bytes
        Stack address       = 0x40196000
        Stack size          = 0x201000 bytes

명령행 인자로 스택 크기를 주면 프로그램에서 스레드 속성 객체를 초기화 하고, 그 객체의 여러 속성들을 설정하고, 그 객체에 대한 포인터를 pthread_create(3) 호출에 전달한다. NTPL 스레딩 구현이 있는 리눅스/x86-32에서 프로그램을 돌리면 다음과 같이 나온다.

$ ./a.out 0x3000000
posix_memalign() allocated at 0x40197000
Thread attributes:
        Detach state        = PTHREAD_CREATE_DETACHED
        Scope               = PTHREAD_SCOPE_SYSTEM
        Inherit scheduler   = PTHREAD_EXPLICIT_SCHED
        Scheduling policy   = SCHED_OTHER
        Scheduling priority = 0
        Guard size          = 0 bytes
        Stack address       = 0x40197000
        Stack size          = 0x3000000 bytes

프로그램 소스

#define _GNU_SOURCE     /* pthread_getattr_np() 선언을 위해 */
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>

#define handle_error_en(en, msg) \
        do { errno = en; perror(msg); exit(EXIT_FAILURE); } while (0)

static void
display_pthread_attr(pthread_attr_t *attr, char *prefix)
{
    int s, i;
    size_t v;
    void *stkaddr;
    struct sched_param sp;

    s = pthread_attr_getdetachstate(attr, &i);
    if (s != 0)
        handle_error_en(s, "pthread_attr_getdetachstate");
    printf("%sDetach state        = %s\n", prefix,
            (i == PTHREAD_CREATE_DETACHED) ? "PTHREAD_CREATE_DETACHED" :
            (i == PTHREAD_CREATE_JOINABLE) ? "PTHREAD_CREATE_JOINABLE" :
            "???");

    s = pthread_attr_getscope(attr, &i);
    if (s != 0)
        handle_error_en(s, "pthread_attr_getscope");
    printf("%sScope               = %s\n", prefix,
            (i == PTHREAD_SCOPE_SYSTEM)  ? "PTHREAD_SCOPE_SYSTEM" :
            (i == PTHREAD_SCOPE_PROCESS) ? "PTHREAD_SCOPE_PROCESS" :
            "???");

    s = pthread_attr_getinheritsched(attr, &i);
    if (s != 0)
        handle_error_en(s, "pthread_attr_getinheritsched");
    printf("%sInherit scheduler   = %s\n", prefix,
            (i == PTHREAD_INHERIT_SCHED)  ? "PTHREAD_INHERIT_SCHED" :
            (i == PTHREAD_EXPLICIT_SCHED) ? "PTHREAD_EXPLICIT_SCHED" :
            "???");

    s = pthread_attr_getschedpolicy(attr, &i);
    if (s != 0)
        handle_error_en(s, "pthread_attr_getschedpolicy");
    printf("%sScheduling policy   = %s\n", prefix,
            (i == SCHED_OTHER) ? "SCHED_OTHER" :
            (i == SCHED_FIFO)  ? "SCHED_FIFO" :
            (i == SCHED_RR)    ? "SCHED_RR" :
            "???");

    s = pthread_attr_getschedparam(attr, &sp);
    if (s != 0)
        handle_error_en(s, "pthread_attr_getschedparam");
    printf("%sScheduling priority = %d\n", prefix, sp.sched_priority);

    s = pthread_attr.getguardsize(attr, &v);
    if (s != 0)
        handle_error_en(s, "pthread_attr_getguardsize");
    printf("%sGuard size          = %zu bytes\n", prefix, v);

    s = pthread_attr_getstack(attr, &stkaddr, &v);
    if (s != 0)
        handle_error_en(s, "pthread_attr_getstack");
    printf("%sStack address       = %p\n", prefix, stkaddr);
    printf("%sStack size          = %#zx bytes\n", prefix, v);
}

static void *
thread_start(void *arg)
{
    int s;
    pthread_attr_t gattr;

    /* pthread_getattr_np()는 비표준 GNU 확장이며
       첫 번째 인자에 지정한 스레드의 속성들을 가져온다. */

    s = pthread_getattr_np(pthread_self(), &gattr);
    if (s != 0)
        handle_error_en(s, "pthread_getattr_np");

    printf("Thread attributes:\n");
    display_pthread_attr(&gattr, "\t");

    exit(EXIT_SUCCESS);         /* 모든 스레드 종료 */
}

int
main(int argc, char *argv[])
{
    pthread_t thr;
    pthread_attr_t attr;
    pthread_attr_t *attrp;      /* NULL 또는 &attr */
    int s;

    attrp = NULL;

    /* 명령행 인자가 있으면 그 값으로 스택 크기 속성을 설정하고
       다른 몇 가지 스레드 속성들을 설정한 다음 attrp가 그
       스레드 속성 객체를 가리키도록 설정한다. */

    if (argc > 1) {
        size_t stack_size;
        void *sp;

        attrp = &attr;

        s = pthread_attr_init(&attr);
        if (s != 0)
            handle_error_en(s, "pthread_attr_init");

        s = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
        if (s != 0)
            handle_error_en(s, "pthread_attr_setdetachstate");

        s = pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED);
        if (s != 0)
            handle_error_en(s, "pthread_attr_setinheritsched");

        stack_size = strtoul(argv[1], NULL, 0);

        s = posix_memalign(&sp, sysconf(_SC_PAGESIZE), stack_size);
        if (s != 0)
            handle_error_en(s, "posix_memalign");

        printf("posix_memalign() allocated at %p\n", sp);

        s = pthread_attr_setstack(&attr, sp, stack_size);
        if (s != 0)
            handle_error_en(s, "pthread_attr_setstack");
    }

    s = pthread_create(&thr, attrp, &thread_start, NULL);
    if (s != 0)
        handle_error_en(s, "pthread_create");

    if (attrp != NULL) {
        s = pthread_attr_destroy(attrp);
        if (s != 0)
            handle_error_en(s, "pthread_attr_destroy");
    }

    pause();    /* 다른 스레드에서 exit() 호출할 때 종료 */
}

SEE ALSO

pthread_attr_setaffinity_np(3), pthread_attr_setdetachstate(3), pthread_attr_setguardsize(3), pthread_attr_setinheritsched(3), pthread_attr_setschedparam(3), pthread_attr_setschedpolicy(3), pthread_attr_setscope(3), pthread_attr_setsigmask_np(3), pthread_attr_setstack(3), pthread_attr_setstackaddr(3), pthread_attr_setstacksize(3), pthread_create(3), pthread_getattr_np(3), pthread_setattr_default_np(3), pthreads(7)


2021-03-22