PTHREAD_ATTR_INIT(3) Руководство программиста Linux PTHREAD_ATTR_INIT(3)

ИМЯ

pthread_attr_init, pthread_attr_destroy - инициализирует и уничтожает объект атрибутов нити

ОБЗОР

#include <pthread.h>
int pthread_attr_init(pthread_attr_t *attr);
int pthread_attr_destroy(pthread_attr_t *attr);
Компилируется и компонуется вместе с -pthread.

ОПИСАНИЕ

Функция pthread_attr_init() инициализирует объект атрибутов нити, на который указывает attr, значениями атрибутов по умолчанию. После этого вызова отдельные атрибуты объекта можно изменять с помощью различных соответствующих функций (перечислены в разделе СМОТРИТЕ ТАКЖЕ, а после этого объект можно использовать в одном или нескольких вызовах pthread_create(3) для создания нитей.

Вызов pthread_attr_init() с уже инициализированным объектом атрибутов нити приводит к непредсказуемому поведению.

Когда объект атрибутов нити больше не нужен, он должен быть уничтожен с помощью функции pthread_attr_destroy(). Уничтожение объекта атрибутов нити не влияет на нить, которая была создана с использованием этого объекта.

После уничтожения объекта атрибутов нити его можно инициализировать с помощью pthread_attr_init() повторно. При использовании уничтоженного объекта атрибутов нити другим способом приводит непредсказуемым результатам.

ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ

При успешном выполнении эти функции возвращают 0; при ошибке возвращается ненулевой номер ошибки.

ОШИБКИ

В POSIX.1 описана ошибка ENOMEM для pthread_attr_init(); в Linux эти функции всегда выполняются успешно (тем не менее, в переносимых приложениях нужно учитывать возможность возврата ошибки).

АТРИБУТЫ

Описание терминов данного раздела смотрите в attributes(7).

Интерфейс Атрибут Значение
pthread_attr_init(), pthread_attr_destroy() Безвредность в нитях MT-Safe

СООТВЕТСТВИЕ СТАНДАРТАМ

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

ЗАМЕЧАНИЯ

Тип pthread_attr_t должен считаться со скрытым форматом: любой доступ к объекту помимо функций pthreads является непереносимым и приводит к непредсказуемым результатам.

ПРИМЕР

В программе, представленной ниже, для создания одной нити используется pthread_attr_init() и другие функции, относящиеся к инициализации объекта атрибутов нити. После создания в нити используется функция pthread_getattr_np(3) (нестандартное расширение GNU) для получения атрибутов нити, а затем показываются эти атрибуты.

Если программа запускается без аргументов командной строки, то аргумент attr функции pthread_create(3) равен NULL, и поэтому нить создаётся с атрибутами по умолчанию. При запуске программы на Linux/x86-32 с реализацией нитей NPTL мы увидим следующее:

$ ulimit -s       # стек не ограничен ==> размер стека по умолчанию 2 МБ
unlimited
$ ./a.out
Атрибуты нити:

        Состояние отсоединения     = PTHREAD_CREATE_JOINABLE

        Область                    = PTHREAD_SCOPE_SYSTEM

        Унаследованный планировщик = PTHREAD_INHERIT_SCHED

        Алгоритм планирования      = SCHED_OTHER

        Приоритет планирования     = 0

        Размер защиты              = 4096 байт

        Адрес стека                = 0x40196000

        Размер стека               = 0x201000 байт

Если в командной строке мы укажем размер стека, то программа инициализирует объект атрибутов нити, задаёт различные атрибуты в этом объекте и передаёт указатель на объект в вызов pthread_create(3). При запуске программы на Linux/x86-32 с реализацией нитей NPTL мы увидим следующее:

$ ./a.out 0x3000000
posix_memalign() выделен по адресу 0x40197000
Атрибуты нити:

        Состояние отсоединения     = PTHREAD_CREATE_DETACHED

        Область                    = PTHREAD_SCOPE_SYSTEM

        Унаследованный планировщик = PTHREAD_EXPLICIT_SCHED

        Алгоритм планирования      = SCHED_OTHER

        Приоритет планирования     = 0

        Размер защиты              = 0 байт

        Адрес стека                = 0x40197000

        Размер стека               = 0x3000000 байт

Исходный код программы

#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("%sСостояние отсоединения     = %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("%sОбласть                    = %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("%sУнаследованный планировщик = %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("%sАлгоритм планирования      = %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("%sПриоритет планирования     = %d\n", prefix, sp.sched_priority);

    s = pthread_attr_getguardsize(attr, &v);

    if (s != 0)

        handle_error_en(s, "pthread_attr_getguardsize");

    printf("%sРазмер защиты          = %zu bytes\n", prefix, v);

    s = pthread_attr_getstack(attr, &stkaddr, &v);

    if (s != 0)

        handle_error_en(s, "pthread_attr_getstack");

    printf("%sАдрес стека                = %p\n", prefix, stkaddr);

    printf("%sРазмер стека               = 0x%zx байт\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("Атрибуты нити:\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) {

        int 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() выделен по адресу %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() */
}

СМОТРИТЕ ТАКЖЕ

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_setstack(3), pthread_attr_setstackaddr(3), pthread_attr_setstacksize(3), pthread_create(3), pthread_getattr_np(3), pthread_setattr_default_np(3), pthreads(7)

2019-03-06 Linux