Чтение онлайн

на главную - закладки

Жанры

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

SIG = 41; TID = 4

Примечание

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

sigaction
на:

act.sa_handler = handler;

act.sa_flags = 0;

а заголовок функции

handler
перепишем так:
static void handler(int signo)
. Если теперь мы в точности повторим предыдущий тест, то при посылке процессу- тестеру последовательности
из N сигналов мы получим всего одно сообщение все того же вида. Это наблюдение интересно еще и тем, что оно показывает, что алгоритм взаимодействия сигнала с потоками не зависит от того, какая обработка установлена для этого сигнала: на основе модели сигналов реального времени или на основе модели надежных сигналов.

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

• главный поток (TID = 1) создает 3 новых потока (TID = 2, 3, 4);

• главный поток переходит в пассивное ожидание сигналов, но в его маске доставка посылаемого сигнала (41) заблокирована;

• выполнение функции потока начинается с разблокирования ожидаемого сигнала;

• … 3 потока (TID = 2, 3, 4) ожидают поступления сигнала;

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

Таким образом, сигнал доставляется одному и только одному потоку, который не блокирует этот сигнал. Обработчик сигнала вызывается в контексте (стек, области собственных данных) этого потока. После выполнения обработчика сигнал поглощается. Какому из потоков, находящихся в состоянии блокирования в ожидании сигналов (в масках которых разблокирован данный сигнал), будет доставлен экземпляр сигнала, предсказать невозможно; это так и должно быть исходя из общих принципов диспетчеризации потоков. Но реально этим потоком является поток, последнимперешедший в состояние ожидания. Для того чтобы убедиться в этом, заменим предпоследнюю строку программы (

pause;
) на:

threadfunc(NULL);

Теперь у нас 4 равнозначных потока, ожидающих прихода сигнала, переходящих в состояние ожидания в последовательности: TID = 2, 3, 4, 1. Реакция процесса на приход сигнала изменится на:

SIG = 41, TID = 1

Изменим текст функции потока на ( файл s7.cc):

void* threadfunc(void* data) {

while (true) {

SignalProcmask(0, 0, SIG_UNBLOCK, &sig, NULL);

delay(1);

SignalProcmask(0, 0, SIG_BLOCK, &sig, NULL);

delay(10);

}

}

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

SIG = 41, TID = 1

SIG = 41; TID = 4

SIG = 41; TID = 4

SIG = 41; TID = 1

SIG = 41; TID = 1

SIG = 41; TID = 4

SIG = 41; TID = 4

SIG = 41; TID = 1

SIG = 41; TID = 2

SIG = 41; TID = 2

SIG = 41; TID = 3

SIG = 41; TID = 4

Такая модель вряд ли может быть названа в полной мере «сигналами в потоках», так как сигнал в ней в конечном итоге направляется процессу как контейнеру, содержащему потоки (можно сказать и так: в оболочку адресного пространства процесса). И только после этого в контексте одного из потоков(и в случае множественных потоков, разблокированных на обработку единого сигнала, невозможно предсказать, в контексте какого из них) выполняется обработчик сигнала. Главный поток процесса (TID = 1) в этой схеме участвует в равнозначном качестве (здесь хорошо видно, что устоявшееся понятие «реакция процесса на сигнал» в строгом смысле некорректно).

Перейдем к более конкретным вопросам: как можно продуктивно использовать эту схему в многопоточных приложениях? Рассмотрим сначала случай, когда каждый из рабочих потоков разблокирован на получение одного, свойственного только ему сигнала ( файл s9.cc):

Чередование потоковых сигналов

#include <stdio.h>

#include <iostream.h>

#include <signal.h>

#include <unistd.h>

#include <pthread.h>

#include <time.h>

#include <sys/neutrino.h>

static void handler(int signo, siginfo_t* info, void* context) {

cout << "SIG = " << signo << "; TID = " << pthread_self << endl;

}

void* threadfunc(void* data) {

// блокировать реакцию на все сигналы

sigset_t sig;

sigfillset(&sig);

SignalProcmask(0, 0, SIG_BLOCK, &sig, NULL);

// разблокировать реакцию на свой сигнал

sigemptyset(&sig);

sigaddset(&sig, (int)data);

SignalProcmask(0, 0, SIG_UNBLOCK, &sig, NULL);

// цикл ожидания приходящих сигналов

while (true) pause;

}

int main {

// для обработки всей группы сигналов управления потоками используем

// единую функцию реакции, иначе все было бы гораздо проще.

struct sigaction act;

sigemptyset(&act.sa_mask);

act.sa_sigaction = handler;

act.sa_flags = SA_SIGINFO;

// создаем группу однотипных потоков

Поделиться:
Популярные книги

Последняя Арена 4

Греков Сергей
4. Последняя Арена
Фантастика:
рпг
постапокалипсис
5.00
рейтинг книги
Последняя Арена 4

На изломе чувств

Юнина Наталья
Любовные романы:
современные любовные романы
6.83
рейтинг книги
На изломе чувств

Para bellum

Ланцов Михаил Алексеевич
4. Фрунзе
Фантастика:
попаданцы
альтернативная история
6.60
рейтинг книги
Para bellum

Ротмистр Гордеев 2

Дашко Дмитрий
2. Ротмистр Гордеев
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Ротмистр Гордеев 2

Новый Рал

Северный Лис
1. Рал!
Фантастика:
фэнтези
попаданцы
5.70
рейтинг книги
Новый Рал

На границе империй. Том 3

INDIGO
3. Фортуна дама переменчивая
Фантастика:
космическая фантастика
5.63
рейтинг книги
На границе империй. Том 3

Вечная Война. Книга VII

Винокуров Юрий
7. Вечная Война
Фантастика:
юмористическая фантастика
космическая фантастика
5.75
рейтинг книги
Вечная Война. Книга VII

Live-rpg. эволюция-3

Кронос Александр
3. Эволюция. Live-RPG
Фантастика:
боевая фантастика
6.59
рейтинг книги
Live-rpg. эволюция-3

Смерть может танцевать 3

Вальтер Макс
3. Безликий
Фантастика:
боевая фантастика
5.40
рейтинг книги
Смерть может танцевать 3

Законы Рода. Том 7

Flow Ascold
7. Граф Берестьев
Фантастика:
юмористическое фэнтези
попаданцы
аниме
5.00
рейтинг книги
Законы Рода. Том 7

Неудержимый. Книга III

Боярский Андрей
3. Неудержимый
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Неудержимый. Книга III

Весь цикл «Десантник на престоле». Шесть книг

Ланцов Михаил Алексеевич
Десантник на престоле
Фантастика:
альтернативная история
8.38
рейтинг книги
Весь цикл «Десантник на престоле». Шесть книг

Релокант. Вестник

Ascold Flow
2. Релокант в другой мир
Фантастика:
фэнтези
попаданцы
рпг
5.00
рейтинг книги
Релокант. Вестник

Мымра!

Фад Диана
1. Мымрики
Любовные романы:
современные любовные романы
5.00
рейтинг книги
Мымра!