Олег Цилюрик - QNX/UNIX: Анатомия параллелизма

Тут можно читать онлайн Олег Цилюрик - QNX/UNIX: Анатомия параллелизма - бесплатно ознакомительный отрывок. Жанр: comp-osnet, издательство Символ-Плюс, год 2006. Здесь Вы можете читать ознакомительный отрывок из книги онлайн без регистрации и SMS на сайте лучшей интернет библиотеки ЛибКинг или прочесть краткое содержание (суть), предисловие и аннотацию. Так же сможете купить и скачать торрент в электронном формате fb2, найти и слушать аудиокнигу на русском языке или узнать сколько частей в серии и всего страниц в публикации. Читателям доступно смотреть обложку, картинки, описание и отзывы (комментарии) о произведении.
  • Название:
    QNX/UNIX: Анатомия параллелизма
  • Автор:
  • Жанр:
  • Издательство:
    Символ-Плюс
  • Год:
    2006
  • Город:
    Санкт-Петербург
  • ISBN:
    5-93286-088-Х
  • Рейтинг:
    4.56/5. Голосов: 91
  • Избранное:
    Добавить в избранное
  • Отзывы:
  • Ваша оценка:
    • 100
    • 1
    • 2
    • 3
    • 4
    • 5

Олег Цилюрик - QNX/UNIX: Анатомия параллелизма краткое содержание

QNX/UNIX: Анатомия параллелизма - описание и краткое содержание, автор Олег Цилюрик, читайте бесплатно онлайн на сайте электронной библиотеки LibKing.Ru

Книга адресована программистам, работающим в самых разнообразных ОС UNIX. Авторы предлагают шире взглянуть на возможности параллельной организации вычислительного процесса в традиционном программировании. Особый акцент делается на потоках (threads), а именно на тех возможностях и сложностях, которые были привнесены в технику параллельных вычислений этой относительно новой парадигмой программирования. На примерах реальных кодов показываются приемы и преимущества параллельной организации вычислительного процесса. Некоторые из результатов испытаний тестовых примеров будут большим сюрпризом даже для самых бывалых программистов. Тем не менее излагаемые техники вполне доступны и начинающим программистам: для изучения материала требуется базовое знание языка программирования C/C++ и некоторое понимание «устройства» современных многозадачных ОС UNIX.

В качестве «испытательной площадки» для тестовых фрагментов выбрана ОСРВ QNX, что позволило с единой точки зрения взглянуть как на специфические механизмы микроядерной архитектуры QNX, так и на универсальные механизмы POSIX. В этом качестве книга может быть интересна и тем, кто не использует (и не планирует никогда использовать) ОС QNX: программистам в Linux, FreeBSD, NetBSD, Solaris и других традиционных ОС UNIX.

QNX/UNIX: Анатомия параллелизма - читать онлайн бесплатно ознакомительный отрывок

QNX/UNIX: Анатомия параллелизма - читать книгу онлайн бесплатно (ознакомительный отрывок), автор Олег Цилюрик
Тёмная тема
Сбросить

Интервал:

Закладка:

Сделать

void pthread_testcancel(void);

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

Примечание

( Очень важно!) Достаточно много библиотечных функций могут сами устанавливать точки отмены. Более того, такие функции могут косвенно вызываться из других функций в программе и тем самым неявно устанавливать точки отмены. Информацию о таких функциях следует искать в справочной man-странице по функции pthread_testcancel(). В результате этого эффекта можно получить отмену потока не в той точке, которую вы считаете безопасной и которую явно отмечаете вызовом pthread_testcancel(), а ранее этой точки — когда будет вызвана одна из таких функций. А это, очевидно, вовсе не то, на что вы рассчитывали!

Если состояние отмены потока, как это описывалось ранее, установлено в PTHREAD_CANCEL_DISABLE, то никакая расстановка точек отмены не имеет эффекта и поток остается неотменяемым.

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

void* function(void* data) {

int state;

pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &state);

// ... здесь выполняется инициализация ...

pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);

pthread_setcancelstate(&state, NULL);

while (true) {

struct blockdata *blk = new blockdata;

// ... обработка блока данных blk ...

delete blk;

pthread_testcancel();

}

}

...

pthread_t tid;

...

pthread_create(&tid, NULL, function, NULL);

...

pthread_cancel(tid); // отмена потока

void* res;

pthread_join(tid, &res); // ожидание отмены

if (res != PTHREAD_CANCELED)

cout << "Что-то не так!" << endl;

Наконец, в QNX (но не в POSIX) существует вызов, подобный pthread_cancel(), принудительно отменяющий поток независимо от его установок («желания»):

int pthread_abort(pthread_t thread);

В отличие от pthread_cancel(), этот вызов принудительно и немедленно отменяет поток. Кроме того, никакие процедуры завершения и деструкторы собственных данных потока не выполняются. Очевидно, что в результате такого «завершения» состояния объектов процесса будут просто неопределенными, поэтому такой вызов крайне опасен. При таком способе отмены в программный код, ожидающий завершения на pthread_join(), в качестве результата завершения возвращается константа (тип void*) PTHREAD_ABORTED(аналогично возвращается константа PTHREAD_CANCELEDпри выполнении pthread_cancel()).

Но и этих мер безопасности недостаточно на все случаи жизни, поэтому механизм потоков предусматривает еще один уровень (механизм) страховки.

Стек процедур завершения

Для поддержания корректности состояния объектов процесса каждый поток может помещать (добавлять) в стек процедур завершения (thread's cancellation-cleanup stack) функции, которые при завершении ( pthread_exit()или return) или отмене (по pthread_cancel()) выполняются в порядке, обратном помещению. Для манипуляции со стеком процедур завершения предоставляются вызовы (оба вызова реализуются макроопределениями, но это не суть важно [24] Разница выражается в том, что макрос pthread_cleanup_push() расширяется в фрагмент кода, открывающийся скобкой «{» без соответствующей скобки «}», аналогично pthread_cleanup_pop() закрывается «}», не имея открывающей скобки. Эти вызовы могут располагаться только парами, в противном случае возникнет лексическая ошибка, обнаруживаемая компилятором. ):

void pthread_cleanup_push(void (routine)(void*), void* arg);

где routine— адрес функции завершения, помещаемой в стек; arg— указатель блока данных, который будет передан routine при ее вызове.

Функции завершения (начиная с вершины стека) вызываются со своими блоками данных в случаях, когда:

• поток завершается, выполняя pthread_exit();

• активизируется действие отмены потока, ранее запрошенное по вызову pthread_cancel();

• выполняется второй (комплементарный к pthread_cleanup_push()) вызов с ненулевым значением аргумента:

void pthread_cleanup_pop(int execute);

Этот вызов выталкивает из стека последнюю помещенную туда pthread_cleanup_push()функцию завершения и, если значение executeненулевое, выполняет ее.

Вот как может выглядеть в этой технике безопасный (с позиции возможной асинхронной отмены потока) захват мьютекса:

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

void cleanup(void* arg) { pthread_mutex_unlock(&mutex); }

void* thread_function(void* arg) {

while (true) {

pthread_mutex_lock(&mutex);

pthread_cleanup_push(&cleanup, NULL);

{

// все точки отмены должны быть расставлены в этом блоке!

}

pthread_testcancel();

pthread_cleanup_pop(1);

}

}

«Легковесность» потока

Вот теперь, завершив краткий экскурс использования процессов и потоков, можно вернуться к вопросу, который вскользь уже звучал по ходу рассмотрения: почему и в каком смысле потоки часто называют «легкими процессами» (LWP — lightweight process)?

Выполним ряд тестов по сравнительной оценке временных затрат на создание процесса и потока. Начнем с процесса ( файл p2-1.cc ):

Затраты на порождение нового процесса

struct mbyte { // мегабайтный блок данных

#pragma pack(1)

uint8_t data[1024 * 1024];

#pragma pack(4)

};

int main(int argc, char *argv[]) {

mbyte *blk = NULL;

if (argc > 1 && atoi(argv[1]) > 0) {

blk = new mbyte[atoi(argv[1])];

}

uint64_t t = ClockCycles();

pid_t pid = fork();

if (pid == -1) perror("fork"), exit(EXIT_FAILURE);

if (pid == 0) exit(EXIT_SUCCESS);

if (pid > 0) {

waitpid(pid, NULL, WEXITED);

t = ClockCycles() - t;

}

if (blk != NULL) delete blk;

cout << "Fork time " << cycle2milisec(t)

<< " msec. [" << t << " cycles]" << endl; exit(EXIT_SUCCESS);

}

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

А теперь оценим временные затраты на создание клона процесса в зависимости от объема программы (мы сознательно использовали клонирование процесса вызовом fork(), а не загрузку spawn*()или exec*(), чтобы исключить из результата время загрузки образа процесса из файла):

Читать дальше
Тёмная тема
Сбросить

Интервал:

Закладка:

Сделать


Олег Цилюрик читать все книги автора по порядку

Олег Цилюрик - все книги автора в одном месте читать по порядку полные версии на сайте онлайн библиотеки LibKing.




QNX/UNIX: Анатомия параллелизма отзывы


Отзывы читателей о книге QNX/UNIX: Анатомия параллелизма, автор: Олег Цилюрик. Читайте комментарии и мнения людей о произведении.


Понравилась книга? Поделитесь впечатлениями - оставьте Ваш отзыв или расскажите друзьям

Напишите свой комментарий
x