QNX/UNIX: Анатомия параллелизма
QNX/UNIX: Анатомия параллелизма читать книгу онлайн
Книга адресована программистам, работающим в самых разнообразных ОС UNIX. Авторы предлагают шире взглянуть на возможности параллельной организации вычислительного процесса в традиционном программировании. Особый акцент делается на потоках (threads), а именно на тех возможностях и сложностях, которые были привнесены в технику параллельных вычислений этой относительно новой парадигмой программирования. На примерах реальных кодов показываются приемы и преимущества параллельной организации вычислительного процесса. Некоторые из результатов испытаний тестовых примеров будут большим сюрпризом даже для самых бывалых программистов. Тем не менее излагаемые техники вполне доступны и начинающим программистам: для изучения материала требуется базовое знание языка программирования C/C++ и некоторое понимание «устройства» современных многозадачных ОС UNIX.
В качестве «испытательной площадки» для тестовых фрагментов выбрана ОСРВ QNX, что позволило с единой точки зрения взглянуть как на специфические механизмы микроядерной архитектуры QNX, так и на универсальные механизмы POSIX. В этом качестве книга может быть интересна и тем, кто не использует (и не планирует никогда использовать) ОС QNX: программистам в Linux, FreeBSD, NetBSD, Solaris и других традиционных ОС UNIX.
Внимание! Книга может содержать контент только для совершеннолетних. Для несовершеннолетних чтение данного контента СТРОГО ЗАПРЕЩЕНО! Если в книге присутствует наличие пропаганды ЛГБТ и другого, запрещенного контента - просьба написать на почту [email protected] для удаления материала
Собственные данные потока
Описанной выше схеме общих данных приложения и локальных данных потока, достаточных для большинства «ординарных» приложений, все-таки определенно не хватает гибкости, покрывающей все потребности. Поэтому в расширениях POSIX реального времени вводится третий специфичный механизм создания и манипулирования с данными в потоке — собственные данные потока (thread-specific data). Использование собственных данных потока — самый простой и эффективный способ манипулирования данными, представленными индивидуальными экземплярами данных для каждого потока.
Согласно POSIX операционная система должна поддерживать ограниченное количество объектов собственных данных (POSIX.1 требует, чтобы этот предел не превышал128 объектов на каждый процесс). Ядром системы поддерживается массив из этого количества ключей (тип
pthread_key_t
Рис. 2.4. Ключи экземпляров данных
Когда поток вызывает
pthread_key_create()
void*
NULL
Рис. 2.5. Поток и его собственные данные
На рис. 2.5 представлен массив структур, создаваемый в единичном экземпляре для каждого процессабиблиотекой потоков. Каждый элемент ключа должен быть предварительно инициализирован вызовом
pthread_key_create()
NULL
После размещения блока программа использует вызов
pthread_setspecific()
pthread_getspecific()
Положим, что нам требуется создать
N
DataBlock
class DataBlock {
~DataBlock() { ... }
...
};
void* ThreadProc(void *data) {
// ... здесь будет код, который мы рассмотрим
return NULL;
}
...
for (int i = 0; i < N; i++)
pthread_create(NULL, NULL, &ThreadProc, NULL);
Последовательность действий потока выглядит следующим образом:
1. Поток запрашивает
pthread_key_create()
DataBlock
DataBlock_1
DataBlock_2
DataBlock_m
m
2. Неприятность здесь состоит в том, что запросить значение ключа для
DataBlock
DataBlock
pthread_once()
3. После этого каждый поток (как создавший ключ, так и использующий его) должен запросить по
pthread_getspecific()
NULL
pthread_setspecific()
4. Дальше поток может работать с собственным экземпляром данных (отдельный экземпляр на каждый поток), используя для доступа к нему
pthread_getspecific()
5. При завершении любого потока система уничтожит и его экземпляр данных, вызвав для него деструктор, который был установлен вызовом
pthread_key_create()
Теперь запишем это в коде, заодно трансформировав в новую функцию
ThreadProc()
SingleProc()
void* SingleProc(void *data) {
static DataBlock db( ... );
// ... операции с полями DataBlock
return NULL;
}
To, что типы параметров и возвращаемое значение
SingleProc()
ThreadProc()