Олег Цилюрик - 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: Анатомия параллелизма - читать книгу онлайн бесплатно (ознакомительный отрывок), автор Олег Цилюрик
Тёмная тема
Сбросить

Интервал:

Закладка:

Сделать
Примечание

Устоявшаяся терминология «запускаемый процесс» относительно exec*()явно неудачна и лишь вводит в заблуждение. Здесь гораздо уместнее говорить о замещении выполнявшегося до этой точки кода новым, выполнение которого начинается с точки входа главного потока замещающего процесса.

Примечание

Если вызов exec*()выполняется из многопоточного родительского процесса, то все выполняющиеся потоки этого процесса предварительно завершаются. Никакие функции деструкторов для них не выполняются.

Если вызов exec*()успешен, управление никогда уже не возвращается в точку вызова. В случае неудачи возвращается -1 и errnoустанавливается так же, как описано выше для spawn().

В качестве примера работы вызова spawn*()(использование exec()аналогично) рассмотрим приложение ( файлы p1.cc, p1ch.cc ), в котором:

• Родительский процесс ( p1 ) порождает дочерний ( p1ch ) и ожидает от него поступления сигнала SIGUSR1(сигналы детально обсуждаются позже, но здесь попутно «вскроем» одну из их особенностей).

• Дочерний процесс периодически посылает родителю сигнал SIGUSR1.

• Родительский процесс может переустановить (с помощью параметров командной строки запуска) для дочернего: период посылки сигнала (1-й параметр задан в нашем приложении константой) и приоритет, с которым будет выполняться дочерний процесс (2-й параметр, в качестве которого ретранслируется единственный параметр команды запуска родителя).

Примечание

В данный момент нас интересует только то приложение, в котором дочерний процесс порождается вызовом spawnl(). Используемые приложением механизмы и понятия — сигналы UNIX приоритеты, наследование и инверсия приоритетов — будут рассмотрены позже, поэтому при первом чтении их можно опустить. Нам не хотелось перегружать текст дополнительными «пустыми» примерами, лишь иллюстрирующими применение одной функции. Это приложение, созданное «на будущее», позволит нам отследить крайне актуальный для систем реального времени вопрос о наличии (или отсутствии) наследования приоритетов при посылке сигналов (допустимо как одно, так и другое решение, но оно должно быть однозначно единственным для ОС).

Итак, родительское приложение ( файл p1.cc ):

Сигналы и наследование приоритетов

#include

#include

#include

#include

#include

#include

// обработчик сигнала

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

int oldprio = getprio(0);

setprio(0, info->si_value, sival_int);

cout << "SIG = " << signo << " old priority = "

<< oldprio << " new priority = " << getprio(0) << endl;

setprio(0, oldprio);

}

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

// установить обработчик сигнала

sigset_t sig;

sigemptyset(&sig);

//определение #define SIGUSR1 16

sigaddset(&sig, SIGUSR1);

sigprocmask(SIG_BLOCK, &sig, NULL);

struct sigaction act;

act.sa_mask = sig;

act.sa_sigaction = handler;

act.sa_flags = SA_SIGINFO;

if (sigaction(SIGUSR1, &act, NULL) < 0)

perror("set signal handler"), exit(EXIT_FAILURE);

// создать новый (дочерний) процесс

const char* prg = "./p1ch", *sdelay = "3";

pid_t pid =

((argc > 1 ) && (atoi(argv[1]) >= sched_get_priority_min(SCHED_RR)) &&

(atoi(argv[1]) <= sched_get_priority_max(SCHED_RR))) ?

spawnl(P_NOWAIT, prg, prg, sdelay, argv[1], NULL) :

spawnl(P_NOWAIT, prg, prg, sdelay, NULL);

if (pid == -1)

perror("spawn child process"), exit(EXIT_FAILURE);

// размаскировать и ожидать сигнала.

sigprocmask(SIG_UNBLOCK, &sig, NULL);

while (true) {

if (sleep(3) != 0) continue;

cout << "parent main loop: priority = " << getprio(0) << endl;

}

}

Дочернее приложение ( файл p1ch.cc ), которое и будет запускать показанный выше родительский процесс:

#include

#include

#include

#include

#include

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

int val, del = 5;

if ((argc > 1) &&

(sscanf(argv[1], "%i", &val) == 1) && (val > 0)) del = val;

if ((argc > 2) &&

(sscanf(argv[2], "%i", &val) == 1 ) && (val > 0) &&

(val <= sched_get_priority_max(SCHED_RR)))

if (setprio(0, val) == -1) perror("set priority");

// периодически уведомлять родителя SIGUSR1, используя

// его как сигнал реального времени (с очередью):

while(true) {

sleep(del);

union sigval val;

val.sival_int = getprio(0);

// #define SIGUSR1 16

sigqueue(getppid(), SIGUSR1, val);

}

}

Примечание

Для многих сигналов действием на их получение, предопределенным по умолчанию, является завершение процесса. (Реже встречается действие по умолчанию — игнорировать полученный сигнал при отсутствии явно установленной для него функции обработчика.) Достаточно странно, что завершение процесса предусмотрено как реакция по умолчанию на получение «пользовательских» сигналов SIGUSR1 и SIGUSR2. Если показанное выше приложение в процессе отладки запустить вызовом из командной строки (из командного интерпретатора или, например, файлового менеджера mqc), то результатом (на первый взгляд не столь ожидаемым) станет завершение интерпретатора командной строки (родительского процесса) и, как следствие, самого тестируемого приложения.

Вот как выглядит начальный участок совместной работы двух процессов:

# p1 15

parent main loop: priority = 10

SIG = 16: old priority = 10, new priority = 15

SIG = 16: old priority = 10, new priority = 15

parent main loop: priority = 10

SIG = 16: old priority = 10, new priority = 15

parent main loop: priority = 10

SIG = 16: old priority = 10, new priority = 15

parent main loop priority = 10

SIG = 16: old priority = 10, new priority = 15

parent main loop: priority = 10

SIG = 16: old priority = 10, new priority = 15

parent main loop: priority = 10

Отчетливо видно, что при посылке сигналов реального времени наследование приоритета посылающего процесса не происходит (дочернее приложение, посылающее сигнал, выполняется с приоритетом 15, а обработчик полученного сигнала в родительском процессе выполняется с приоритетом по умолчанию, равным 10).

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

Завершение процесса

С завершением процесса дело обстоит достаточно просто, по крайней мере, в сравнении с тем, что происходит при завершении потока, как это и будет показано очень скоро. Процесс завершается, если программа выполняет вызов exit()или выполнение просто доходит до точки завершения функции main(), будь то с явным указанием оператора returnили без оного. Это естественный, внутренний (из программного кода самого процесса) путь завершения.

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

Интервал:

Закладка:

Сделать


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

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




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


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


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

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