Необязательные компоненты библиотеки работы с нитями

В данном разделе описаны расширенные атрибуты нитей, взаимных блокировок и переменных условий.

В стандарте библиотек нитей POSIX реализация некоторых компонентов объявлена необязательной. Все функции, определенные с помощью API библиотеки нитей, доступны всегда. Некоторые функции могут быть не реализованы. Приложения могут вызывать нереализованные функции, но такие функции всегда будут возвращать код ошибки ENOSYS.

Атрибуты стека

Для каждой нити выделяется собственный стек. Управление стеком зависит от реализации. Таким образом, приведенная ниже информация применима только к AIX, хотя подобные функции могут существовать и в других системах.

Стек выделяется динамически при создании нити. С помощью расширенных атрибутов нити пользователь может управлять размером стека и задавать его адрес. Приведенная ниже информация не относится к начальной нити, создаваемой системой.

Размер стека

С помощью размера стека можно изменять значение атрибута stacksize в объекте атрибутов нити. Этот атрибут указывает минимальный размер области памяти, отведенной под стек для вновь созданной нити.

В системе AIX определен атрибут stacksize. Если этот необязательный компонент реализован, то доступны следующие атрибуты и функции:

Значение атрибута stacksize по умолчанию равно 96 Кб. Минимальное значение атрибута stacksize по умолчанию равно 16 Кб. Если указанное значение меньше минимального, то будет применяться минимальное значение.

В библиотеке поддержки нитей AIX для каждой новой нити выделяется блок данных, называемый пользовательской областью нити. Этот блок состоит из следующих компонентов:
  • Красная зона, защищенная от чтения и записи, предназначена для обнаружения переполнения стека. В программах с большими страницами красная зона не предусмотрена.
  • Стек по умолчанию.
  • Структура pthread.
  • Структура thread.
  • Структура атрибутов thread.
Прим.: Необходимо различать пользовательскую область нити, описанную здесь, и структуру uthread, применяемую в ядре AIX. Пользовательская область нити доступна только в пользовательском режиме и управляет ей исключительно библиотека нитей, в то время как структура uthread существует только в среде ядра.

Адрес стека компонента POSIX

С адресом стека связано значение атрибута stackaddr в объекте атрибутов нити. Этот атрибут указывает место в памяти, отведенное под стек для вновь созданной нити.

Если этот необязательный компонент реализован, то доступны следующие атрибуты и функции:
  • Атрибут stackaddr задает адрес стека, выделяемого нити.
  • Функция pthread_attr_getstackaddr возвращает значение атрибута.
  • Функция pthread_attr_setstackaddr задает значение атрибута.

Если адрес не указан, то нити выделяется стек с произвольным адресом. Если стек необходимо определить по конкретному адресу, то вы можете воспользоваться атрибутом stackaddr. Например, если нужен стек очень большого размера, вы можете указать для него адрес из свободного сегмента.

Если адрес стека был указан при вызове функции pthread_create, то система попытается выделить стек по этому адресу. Если сделать это невозможно, то функция pthread_create вернет значение EINVAL. Функция pthread_attr_setstackaddr возвращает ошибку только в том случае, если указанный адрес стека не попадает в адресное пространство.

Планирование приоритета компонента POSIX

Планирование приоритета позволяет управлять планированием нитей. Если эта функция отключена, то параметры планирования всех нитей в процессе наследуются от самого процесса. Если же она включена, то каждая нить имеет свой набор параметров планирования. Для нитей с локальной областью действия с параметрами планирования работает планировщик библиотеки на уровне процесса, в то время как параметры планирования нитей с глобальной областью действия обрабатывает планировщик ядра на системном уровне.

Если этот необязательный компонент реализован, то доступны следующие атрибуты и функции:

  • Атрибут inheritsched из объекта атрибутов нити
  • Атрибут schedparam из объекта атрибутов нити и из самой нити
  • Атрибут schedpolicy из объекта атрибутов нити и из самой нити
  • Атрибут contention-scope из объекта атрибутов нити и из самой нити
  • Функции pthread_attr_getschedparam и pthread_attr_setschedparam
  • Функция pthread_getschedparam

Проверка наличия необязательного компонента

Проверить наличие необязательных компонентов можно как на этапе компиляции, так и на этапе выполнения. Переносимые программы должны проверять наличие необязательных компонентов до начала работы с ними, чтобы не приходилось изменять исходный код программ при переносе в другую систему.

Проверка во время компиляции

Если окажется, что какой-либо необязательный компонент недоступен, то компиляцию можно прервать так:
#ifndef _POSIX_THREAD_ATTR_STACKSIZE
#error "Необходимо наличие компонента POSIX - Размер стека"
#endif
В файле заголовков pthread.h определяются также символы, которые могут применяться другими файлами заголовков или программами. Эти символы перечислены ниже:
_POSIX_REENTRANT_FUNCTIONS
Означает, что необходимы реентерабельные функции.
_POSIX_THREADS
Означает реализацию библиотеки нитей.

Проверка во время выполнения

Для проверки наличия необязательных компонентов в системе на этапе выполнения программы можно применять функцию sysconf. Она оказывается весьма полезной при переносе программ в двоично-совместимую систему, например, в систему под управлением другой версии AIX.

Ниже приведен список символьных констант, связанных со всеми необязательными компонентами. Эти символьные константы необходимо передать в функцию sysconf в параметре Name. Константы определены в файле заголовка unistd.h.

Адрес стека
_SC_THREAD_ATTR_STACKADDR
Размер стека
_SC_THREAD_ATTR_STACKSIZE
Планирование приоритета
_SC_THREAD_PRIORITY_SCHEDULING
Наследование приоритета
_SC_THREAD_PRIO_INHERIT
Защита приоритета
_SC_THREAD_PRIO_PROTECT
Совместное выполнение процессов
_SC_THREAD_PROCESS_SHARED
Наличие основных компонентов можно проверить, вызвав функцию sysconf со следующими значениями параметра имя:
_SC_REENTRANT_FUNCTIONS
Означает, что необходимы реентерабельные функции.
_SC_THREADS
Означает реализацию библиотеки нитей.

Совместное выполнение процессов

В AIX и большинстве систем UNIX допускается использование несколькими процессами одного пространства данных, называемого общей памятью. Атрибуты совместного выполнения процессов, задаваемые для переменных условий и взаимных блокировок, позволяют размещать эти объекты в общей памяти для синхронизации нитей различных процессов. Однако стандартного интерфейса управления общей памятью не существует, поэтому опция POSIX для общих процессов в AIX не реализована.

Типы данных библиотеки нитей

Для работы с библиотекой нитей определены следующие типы данных определены. Определения этих типов данных могут быть различными в различных системах.
pthread_t
Идентифицирует нить.
pthread_attr_t
Идентифицирует объект атрибутов нити.
pthread_cond_t
Идентифицирует условную переменную.
pthread_condattr_t
Идентифицирует объект атрибутов условной переменной.
pthread_key_t
Идентифицирует ключ данных для конкретной нити.
pthread_mutex_t
Идентифицирует взаимную блокировку.
pthread_mutexattr_t
Идентифицирует объект атрибутов взаимной блокировки.
pthread_once_t
Идентифицирует объект разовой инициализации.

Ограничения и значения по умолчанию

В библиотеке нитей есть несколько ограничений и значений по умолчанию, зависящих от реализации. Для улучшения переносимости программ можно считывать эти ограничения и значения по умолчанию в виде символьных констант:
  • В процессе не может быть более 512 нитей. Максимальное количество нитей можно получить на этапе компиляции с помощью символьной константы PTHREAD_THREADS_MAX, определенной в файле заголовка pthread.h. Если приложение скомпилировано с флагом -D_LARGE_THREADS, то максимальное число нитей в одном процессе равно 32767.
  • Минимальный размер стека для одной нити составляет 8 Кб. По умолчанию размер стека равен 96 Кб. Минимальный размер стека можно получить на этапе компиляции с помощью символьной константы PTHREAD_STACK_MIN, определенной в файле заголовка pthread.h.
    Прим.: Максимальный размер стека составляет 256 Мб, что равно размеру сегмента. Это ограничение можно получить с помощью символьной константы PTHREAD_STACK_MAX в файле заголовка pthread.h.
  • Максимальное значение этого параметра - 508. Это значение можно получить на этапе компиляции с помощью символьной константы PTHREAD_KEYS_MAX, определенной в файле заголовка pthread.h.

Значения атрибутов по умолчанию

Значения атрибутов нитей по умолчанию определены в файле заголовка pthread.h и связаны со следующими символьными константами:
  • Значение символьной константы DEFAULT_DETACHSTATE по умолчанию равно PTHREAD_CREATE_DETACHED и задает значение атрибута detachstate по умолчанию.
  • Значение символьной константы DEFAULT_JOINABLE по умолчанию равно PTHREAD_CREATE_JOINABLE и задает значение объединяемого состояния по умолчанию.
  • Значение символьной константы DEFAULT_INHERIT по умолчанию равно PTHREAD_INHERIT_SCHED и задает значение атрибута inheritsched по умолчанию.
  • Значение символьной константы DEFAULT_PRIO по умолчанию равно 1 и задает значение по умолчанию для поля sched_prio атрибута schedparam.
  • Значение символьной константы DEFAULT_SCHED по умолчанию равно SCHED_OTHER и задает значение атрибута нитей schedpolicy по умолчанию.
  • Значение символьной константы DEFAULT_SCOPE по умолчанию равно PTHREAD_SCOPE_LOCAL и задает значение атрибута contention-scope по умолчанию.