- Любовные романы
- Фантастика и фэнтези
- Ненаучная фантастика
- Ироническое фэнтези
- Научная Фантастика
- Фэнтези
- Ужасы и Мистика
- Боевая фантастика
- Альтернативная история
- Космическая фантастика
- Попаданцы
- Юмористическая фантастика
- Героическая фантастика
- Детективная фантастика
- Социально-психологическая
- Боевое фэнтези
- Русское фэнтези
- Киберпанк
- Романтическая фантастика
- Городская фантастика
- Технофэнтези
- Мистика
- Разная фантастика
- Иностранное фэнтези
- Историческое фэнтези
- LitRPG
- Эпическая фантастика
- Зарубежная фантастика
- Городское фентези
- Космоопера
- Разное фэнтези
- Книги магов
- Любовное фэнтези
- Постапокалипсис
- Бизнес
- Историческая фантастика
- Социально-философская фантастика
- Сказочная фантастика
- Стимпанк
- Романтическое фэнтези
- Ироническая фантастика
- Детективы и Триллеры
- Проза
- Юмор
- Феерия
- Новелла
- Русская классическая проза
- Современная проза
- Повести
- Контркультура
- Русская современная проза
- Историческая проза
- Проза
- Классическая проза
- Советская классическая проза
- О войне
- Зарубежная современная проза
- Рассказы
- Зарубежная классика
- Очерки
- Антисоветская литература
- Магический реализм
- Разное
- Сентиментальная проза
- Афоризмы
- Эссе
- Эпистолярная проза
- Семейный роман/Семейная сага
- Поэзия, Драматургия
- Приключения
- Детская литература
- Загадки
- Книга-игра
- Детская проза
- Детские приключения
- Сказка
- Прочая детская литература
- Детская фантастика
- Детские стихи
- Детская образовательная литература
- Детские остросюжетные
- Учебная литература
- Зарубежные детские книги
- Детский фольклор
- Буквари
- Книги для подростков
- Школьные учебники
- Внеклассное чтение
- Книги для дошкольников
- Детская познавательная и развивающая литература
- Детские детективы
- Домоводство, Дом и семья
- Юмор
- Документальные книги
- Бизнес
- Работа с клиентами
- Тайм-менеджмент
- Кадровый менеджмент
- Экономика
- Менеджмент и кадры
- Управление, подбор персонала
- О бизнесе популярно
- Интернет-бизнес
- Личные финансы
- Делопроизводство, офис
- Маркетинг, PR, реклама
- Поиск работы
- Бизнес
- Банковское дело
- Малый бизнес
- Ценные бумаги и инвестиции
- Краткое содержание
- Бухучет и аудит
- Ораторское искусство / риторика
- Корпоративная культура, бизнес
- Финансы
- Государственное и муниципальное управление
- Менеджмент
- Зарубежная деловая литература
- Продажи
- Переговоры
- Личная эффективность
- Торговля
- Научные и научно-популярные книги
- Биофизика
- География
- Экология
- Биохимия
- Рефераты
- Культурология
- Техническая литература
- История
- Психология
- Медицина
- Прочая научная литература
- Юриспруденция
- Биология
- Политика
- Литературоведение
- Религиоведение
- Научпоп
- Психология, личное
- Математика
- Психотерапия
- Социология
- Воспитание детей, педагогика
- Языкознание
- Беременность, ожидание детей
- Транспорт, военная техника
- Детская психология
- Науки: разное
- Педагогика
- Зарубежная психология
- Иностранные языки
- Филология
- Радиотехника
- Деловая литература
- Физика
- Альтернативная медицина
- Химия
- Государство и право
- Обществознание
- Образовательная литература
- Учебники
- Зоология
- Архитектура
- Науки о космосе
- Ботаника
- Астрология
- Ветеринария
- История Европы
- География
- Зарубежная публицистика
- О животных
- Шпаргалки
- Разная литература
- Зарубежная литература о культуре и искусстве
- Пословицы, поговорки
- Боевые искусства
- Прочее
- Периодические издания
- Фанфик
- Военное
- Цитаты из афоризмов
- Гиды, путеводители
- Литература 19 века
- Зарубежная образовательная литература
- Военная история
- Кино
- Современная литература
- Военная техника, оружие
- Культура и искусство
- Музыка, музыканты
- Газеты и журналы
- Современная зарубежная литература
- Визуальные искусства
- Отраслевые издания
- Шахматы
- Недвижимость
- Великолепные истории
- Музыка, танцы
- Авто и ПДД
- Изобразительное искусство, фотография
- Истории из жизни
- Готические новеллы
- Начинающие авторы
- Спецслужбы
- Подростковая литература
- Зарубежная прикладная литература
- Религия и духовность
- Старинная литература
- Справочная литература
- Компьютеры и Интернет
- Блог
Основы программирования в Linux - Нейл Мэтью
Шрифт:
Интервал:
Закладка:
В примере с отсоединенным или обособленным потоком thread5.c вы создаете атрибут потока, задаете состояние потока как отсоединенное и затем создаете с помощью этого атрибута поток. Теперь, когда закончится дочерний поток, он вызовет обычным образом pthread_exit. В это время исходный поток больше не ждет созданный им поток для присоединения. В данном примере используется простой флаг thread_finished, чтобы позволить потоку main определить, закончился ли дочерний поток, и показать, что потоки все еще совместно используют переменные.
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <pthread.h>
void *thread_function(void *arg);
char message[] = "Hello World";
int thread_finished = 0;
int main() {
int res;
pthread_t a_thread;
pthread_attr_t thread_attr;
res = pthread_attr_init(&thread_attr);
if (res != 0) {
perror("Attribute creation failed");
exit(EXIT_FAILURE);
}
res = pthread_attr_setdetachstate(&thread_attr,
PTHREAD_CREATE_DETACHED);
if (res != 0) {
perror("Setting detached attribute failed");
exit(EXIT_FAILURE);
}
res = pthread_create(&a_thread, &thread_attr,
thread_function, (void *)message);
if (res != 0) {
perror("Thread creation failed");
exit(EXIT_FAILURE);
}
(void)pthread_attr_destroy(&thread_attr);
while (!thread_finished) {
printf("Waiting for thread to say it's finished...n");
sleep(1);
}
printf("Other thread finished, bye!n");
exit(EXIT_SUCCESS);
}
void *thread_function(void *arg) {
printf("thread_function is running. Argument was %sn", (char *)arg);
sleep(4);
printf("Second thread setting finished flag, and exiting nown");
thread_finished = 1;
pthread_exit(NULL);
}
Вывод не принесет сюрпризов:
$ ./threads
Waiting for thread to say it's finished...
thread_function is running. Argument was Hello World
Waiting for thread to say it's finished...
Waiting for thread to say it's finished...
Waiting for thread to say it's finished...
Second thread setting finished flag, and exiting now
Other thread finished, bye!
Как видите, установка отсоединенного состояния позволяет второму потоку завершиться независимо, без необходимости исходному потоку ждать этого события.
Как это работает
В исходном тексте программы два важных фрагмента:
pthread_attr_t thread_attr;
res = pthread_attr_init(&thread_attr);
if (res != 0) {
perror("Attribute creation failed");
exit(EXIT_FAILURE);
}
который объявляет атрибут потока и инициализирует его, и
res = pthread_attr_setdetachstatе(&thread_attr, PTHREAD_CREATE_DETACHED);
if (res != 0) {
perror("Setting detached attribute failed");
exit(EXIT_FAILURE);
}
который устанавливает значения атрибутов для задания отсоединенного состояния потока.
К другим незначительным отличиям относится создание потока с передачей адреса атрибутов:
res = pthread_create(&a_thread, &thread_attr, thread_function, (void*)message);
и для завершенности уничтожение атрибутов после их использования:
pthread_attr_destroy(&thread_attr);
Атрибуты планирования потока
Давайте рассмотрим второй атрибут потока, который вам, возможно, захочется изменить, — атрибут планирования. Изменение этого атрибута очень похоже на установку отсоединенного состояния потока, но есть дополнительные функции, которые можно применять для подбора допустимых уровней приоритета, sched_get_priority_max и sched_get_priority_min.
Выполните упражнение 12.6.
Упражнение 12.6. ПланированиеПоскольку данная программа thread6.c очень похожа на программу предыдущего упражнения, мы рассмотрим только отличия.
1. Прежде всего, вам понадобится несколько дополнительных переменных:
int max_priority;
int min_priority;
struct sched_param scheduling_value;
2. После того как установлен атрибут отсоединения, вы задаете политику планирования:
res = pthread_attr_setschedpolicy(&thread_attr, SCHED_OTHER);
if (res != 0) {
perror("Setting scheduling policy failed");
exit(EXIT_FAILURE);
}
3. Далее находите диапазон допустимых приоритетов
max_priority = sched_get_priority_max(SCHED_OTHER);
min_priority = sched_get_priority_min(SCHED_OTHER);
и задаете один из них:
scheduling_value.sched_priority = min_priority;
res = pthread_attr_setschedparam(&thread_attr, &scheduling_value);
if (res != 0) {
perror("Setting scheduling priority failed");
exit(EXIT_FAILURE);
}
Когда вы запустите программу, то получите следующий вывод:
$ ./thread6
Waiting for thread to say it's finished...
thread_function is running. Argument was Hello World
Waiting for thread to say it's finished...
Waiting for thread to say it's finished...
Waiting for thread to say it's finished...
Second thread setting finished flag, and exiting now
Other thread finished, bye!
Как это работает
Этот пример очень похож на установку атрибута отсоединенного состояния за исключением того, что вы задаете вместо него способ планирования.
Отмена потока
Иногда требуется, чтобы один поток попросил другой завершиться досрочно способом, очень похожим на отправку ему сигнала. Сделать это можно с помощью потоков и параллельно с помощью обработки сигнала; у потоков появляется возможность изменить свое поведение, когда их просят завершиться.
Давайте сначала рассмотрим функцию для создания запроса на завершение потока.
#include <pthread.h>
int pthread_cancel(pthread_t thread);
Она достаточно проста: имея идентификатор потока, вы можете запросить его аннулирование. На приемном конце запроса на отмену все немного сложнее, но не слишком. Поток может установить состояние отмены с помощью функции pthread_setcancelstate.
#include <pthread.h>
int pthread_setcancelstate(int state, int *oldstate);
Первый параметр равен либо значению PHTREAD_CANCEL_ENABLE, позволяющему получать запросы на отмену, либо PTHREAD_CANCEL_DISABLE, заставляющему игнорировать подобные запросы. Указатель oldstate дает возможность получить предыдущее состояние. Если оно вас не интересует, можно просто передать в этом параметре NULL. Если запросы на отмену принимаются, есть второй уровень управления, принимаемый потоком, — тип отмены, который задается функцией pthread_setcanceltype.
#include <pthread.h>
int pthread_setcanceltype(int type, int *oldtype);
Тип отмены может принимать одно из следующих значений: PTHREAD_CANCEL_ASYNCHRONOUS, заставляющее обрабатывать запросы на отмену немедленно, и PTHREAD_CANCEL_DEFERRED, заставляющее запросы на отмену ждать, пока поток не выполнит одну из следующих функций: pthread_join, pthread_cond_wait, pthread_cond_timedwait, pthread_testcancel, sem_wait или sigwait.
Мы не описываем все эти функции в данной главе, поскольку, как правило, не все они нужны. Когда они понадобятся, вы сможете найти дополнительную информацию на страницах интерактивного справочного руководства.
ПримечаниеВ соответствии со стандартом POSIX системные вызовы, способные задерживать выполнение, такие как read, wait и т.д., должны также быть точками отмены потока. Во время написания книги поддержка этого стандарта в ОС Linux представлялась незавершенной. Но кое-какая работа была проделана, скажем, некоторые задерживающие вызовы, такие как sleep, на самом деле допускают отмену. Для того чтобы обезопасить себя, добавляйте вызовы pthread_testcancel в программный код, который по вашим расчетам может быть отменен.
Параметр oldtype позволяет получить предыдущее состояние, если оно вас не интересует, можно передать NULL. По умолчанию потоки запускаются с состоянием отмены, равным PTHREAD_CANCEL_ENABLE, и типом отмены — PTHREAD_CANCEL_DEFERRED.
Выполните упражнение 12.7.
Упражнение 12.7. Отмена потокаПрограмма thread7.c — ещё один потомок программы thread1.с. На этот раз основной поток отправляет запрос на отмену потока, который он создал.
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <pthread.h>
void *thread_function(void *arg);
int main() {
int res;
pthread_t a_thread;
void *thread_result;
res = pthread_create(&a_thread, NULL, thread_function, NULL);
if (res != 0) {
perror("Thread creation failed");
exit(EXIT_FAILURE);
}
sleep(3);
printf("Canceling thread...n");
res = pthread_cancel(a_thread);
if (res != 0) {
perror("Thread cancelation failed");
exit(EXIT_FAILURE);
}
printf("Waiting for thread to finish...n");

