pthread_getattr_np(3)

НАИМЕНОВАНИЕ
pthread_getattr_np - возвращает атрибуты созданной нити

БИБЛИОТЕКА
Библиотека потоков POSIX (libpthread, -lpthread)

СИНТАКСИС
#define _GNU_SOURCE             /* Смотрите feature_test_macros(7) */
#include <pthread.h>

int pthread_getattr_np(pthread_t thread, pthread_attr_t *attr);

ОПИСАНИЕ
Функция pthread_getattr_np() инициализирует объект атрибутов нити, на который указывает attr, так, чтобы он содержал актуальные значения атрибутов выполняющейся нити thread.

Возвращаемые значения атрибутов могут отличаться от соответствующих значений атрибутов переданных в объекте attr, который использовался при создании нити с помощью pthread_create(3). В частности, могут отличаться следующие атрибуты:

•   состояние отсоединения, так как присоединяемая нить могла сама отсоединиться после создания;

•   размер стека, так как реализация нитей могла выронить значение по уместной границе.

•   размер защиты, так как реализация нитей могла округлить значение в большую сторону до кратного размера страницы, или проигнорировать (т. е., посчитать за 0), если приложение само выделяет себе стек.

Кроме этого, если атрибут адреса стека не был указан в объекте атрибутов нити при создании нити, то возвращаемый объект атрибутов нити будет содержать актуальный адрес стека, который был выбран реализацией для нити.

Когда объект атрибутов нити, возвращаемый pthread_getattr_np(), больше не требуется, то он должен быть удалён с помощью pthread_attr_destroy(3).

ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ
При успешном выполнении функция возвращает 0; при ошибке возвращается ненулевой номер ошибки.

ОШИБКИ

ENOMEM
    Недостаточно памяти.

Также, если thread указывает на главную нить, то pthread_getattr_np() может завершиться с ошибкой из-за ошибок различных используемых вызовов: fopen(3), если невозможно открыть /proc/self/maps; getrlimit(2), если не поддерживается ограничение ресурса RLIMIT_STACK.

АТРИБУТЫ
Описание терминов данного раздела смотрите в attributes(7).
Интерфейс | Атрибут | Значение
pthread_getattr_np() | Безвредность в нитях | MT-Safe

СТАНДАРТЫ
GNU; отсюда и суффикс "_np" (непереносимый) в названии.

ИСТОРИЯ
glibc 2.2.3.

ПРИМЕРЫ
В программе, показанной далее, демонстрируется использование pthread_getattr_np(). Программа создаёт нить, которая, затем, использует pthread_getattr_np() для получения и показа своих атрибутов размера защиты, адреса стека и размера стека. Аргументами командной строки можно изменить эти атрибуты. Работа программы показана далее.

В этом запуске на системе x86-32 нить создаётся со значениями атрибутов по умолчанию:

    $ ulimit -s      # Без ограничения стека ==>
                     # размер стека по умолчанию 2 МБ
    unlimited
    $ ./a.out
    Атрибуты созданной нити:
            Размер защиты      = 4096 байт
            Адрес стека        = 0x40196000 (EOS = 0x40397000)
            Размер стека       = 0x201000 (2101248) байт

В этом запуске мы видим, что при задании размера защиты его значение округляется до значение следующего кратного размера системной страницы (4096 байт на x86-32):

    $ ./a.out -g 4097
    Thread attributes object after initializations:
            Guard size          = 4097 bytes
            Stack address       = (nil)
            Stack size          = 0x0 (0) bytes

    Attributes of created thread:
            Guard size          = 8192 bytes
            Stack address       = 0x40196000 (EOS = 0x40397000)
            Stack size          = 0x201000 (2101248) bytes

В этом запуске программа вручную выделяет стек для нити. В этом случае атрибут размера защиты игнорируется.

    $ ./a.out -g 4096 -s 0x8000 -a
    Allocated thread stack at 0x804d000

    Thread attributes object after initializations:
            Guard size          = 4096 bytes
            Stack address       = 0x804d000 (EOS = 0x8055000)
            Stack size          = 0x8000 (32768) bytes

    Attributes of created thread:
            Guard size          = 0 bytes
            Stack address       = 0x804d000 (EOS = 0x8055000)
            Stack size          = 0x8000 (32768) bytes

  Исходный код программы
    #define _GNU_SOURCE     /* To get pthread_getattr_np() declaration */
    #include <err.h>
    #include <errno.h>
    #include <pthread.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>

    static void
    display_stack_related_attributes(pthread_attr_t *attr, char *prefix)
    {
        int s;
        size_t stack_size, guard_size;
        void *stack_addr;

        s = pthread_attr_getguardsize(attr, &guard_size);
        if (s != 0)
            errc(EXIT_FAILURE, s, "pthread_attr_getguardsize");
        printf("%sGuard size          = %zu bytes\n", prefix, guard_size);

        s = pthread_attr_getstack(attr, &stack_addr, &stack_size);
        if (s != 0)
            errc(EXIT_FAILURE, s, "pthread_attr_getstack");
        printf("%sStack address       = %p", prefix, stack_addr);
        if (stack_size > 0)
            printf(" (EOS = %p)", (char *) stack_addr + stack_size);
        printf("\n");
        printf("%sStack size          = %#zx (%zu) bytes\n",
               prefix, stack_size, stack_size);
    }

    static void
    display_thread_attributes(pthread_t thread, char *prefix)
    {
        int s;
        pthread_attr_t attr;

        s = pthread_getattr_np(thread, &attr);
        if (s != 0)
            errc(EXIT_FAILURE, s, "pthread_getattr_np");

        display_stack_related_attributes(&attr, prefix);

        s = pthread_attr_destroy(&attr);
        if (s != 0)
            errc(EXIT_FAILURE, s, "pthread_attr_destroy");
    }

    static void *           /* Start function for thread we create */
    thread_start(void *arg)
    {
        printf("Attributes of created thread:\n");
        display_thread_attributes(pthread_self(), "\t");

        exit(EXIT_SUCCESS);         /* Terminate all threads */
    }

    static void
    usage(char *pname, char *msg)
    {
        if (msg != NULL)
            fputs(msg, stderr);
        fprintf(stderr, "Usage: %s [-s stack-size [-a]]"
                " [-g guard-size]\n", pname);
        fprintf(stderr, "\t\t-a means program should allocate stack\n");
        exit(EXIT_FAILURE);
    }

    static pthread_attr_t *   /* Get thread attributes from command line */
    get_thread_attributes_from_cl(int argc, char *argv[],
                                  pthread_attr_t *attrp)
    {
        int s, opt, allocate_stack;
        size_t stack_size, guard_size;
        void *stack_addr;
        pthread_attr_t *ret_attrp = NULL;   /* Set to attrp if we initialize
                                               a thread attributes object */
        allocate_stack = 0;
        stack_size = -1;
        guard_size = -1;

        while ((opt = getopt(argc, argv, "ag:s:")) != -1) {
            switch (opt) {
            case 'a':   allocate_stack = 1;                     break;
            case 'g':   guard_size = strtoul(optarg, NULL, 0);  break;
            case 's':   stack_size = strtoul(optarg, NULL, 0);  break;
            default:    usage(argv[0], NULL);
            }
        }

        if (allocate_stack && stack_size == -1)
            usage(argv[0], "Specifying -a without -s makes no sense\n");

        if (argc > optind)
            usage(argv[0], "Extraneous command-line arguments\n");

        if (stack_size != -1 || guard_size > 0) {
            ret_attrp = attrp;

            s = pthread_attr_init(attrp);
            if (s != 0)
                errc(EXIT_FAILURE, s, "pthread_attr_init");
        }

        if (stack_size != -1) {
            if (!allocate_stack) {
                s = pthread_attr_setstacksize(attrp, stack_size);
                if (s != 0)
                    errc(EXIT_FAILURE, s, "pthread_attr_setstacksize");
            } else {
                s = posix_memalign(&stack_addr, sysconf(_SC_PAGESIZE),
                                   stack_size);
                if (s != 0)
                    errc(EXIT_FAILURE, s, "posix_memalign");
                printf("Allocated thread stack at %p\n\n", stack_addr);

                s = pthread_attr_setstack(attrp, stack_addr, stack_size);
                if (s != 0)
                    errc(EXIT_FAILURE, s, "pthread_attr_setstacksize");
            }
        }

        if (guard_size != -1) {
            s = pthread_attr_setguardsize(attrp, guard_size);
            if (s != 0)
                errc(EXIT_FAILURE, s, "pthread_attr_setstacksize");
        }

        return ret_attrp;
    }

    int
    main(int argc, char *argv[])
    {
        int s;
        pthread_t thr;
        pthread_attr_t attr;
        pthread_attr_t *attrp = NULL;    /* Set to &attr if we initialize
                                            a thread attributes object */

        attrp = get_thread_attributes_from_cl(argc, argv, &attr);

        if (attrp != NULL) {
            printf("Thread attributes object after initializations:\n");
            display_stack_related_attributes(attrp, "\t");
            printf("\n");
        }

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

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

        pause();    /* Terminates when other thread calls exit() */
    }

СМОТРИТЕ ТАКЖЕ
pthread_attr_getaffinity_np(3), pthread_attr_getdetachstate(3), pthread_attr_getguardsize(3), pthread_attr_getinheritsched(3), pthread_attr_getschedparam(3), pthread_attr_getschedpolicy(3), pthread_attr_getscope(3), pthread_attr_getstack(3), pthread_attr_getstackaddr(3), pthread_attr_getstacksize(3), pthread_attr_init(3), pthread_create(3), pthreads(7)

ПЕРЕВОД
Русский перевод этой страницы руководства разработал(и) Alexey, Azamat Hackimov <azamat.hackimov@gmail.com>, kogamatranslator49 <r.podarov@yandex.ru>, Darima Kogan <silverdk99@gmail.com>, Max Is <ismax799@gmail.com>, Yuri Kozlov <yuray@komyakino.ru> и Иван Павлов <pavia00@gmail.com>

Этот перевод является свободной программной документацией; он распространяется на условиях общедоступной лицензии GNU (GNU General Public License - GPL, https://www.gnu.org/licenses/gpl-3.0.html версии 3 или более поздней) в отношении авторского права, но БЕЗ КАКИХ-ЛИБО ГАРАНТИЙ.

Если вы обнаружите какие-либо ошибки в переводе этой страницы руководства, пожалуйста, сообщите об этом разработчику(ам) по его(их) адресу(ам) электронной почты или по адресу списка рассылки русских переводчиков (debian-l10n-russian@lists.debian.org).