MyBooks.club
Все категории

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

На сайте mybooks.club вы можете бесплатно читать книги онлайн без регистрации, включая Олег Цилюрик - QNX/UNIX: Анатомия параллелизма. Жанр: Программное обеспечение издательство -,. Доступна полная версия книги с кратким содержанием для предварительного ознакомления, аннотацией (предисловием), рецензиями от других читателей и их экспертным мнением.
Кроме того, на сайте mybooks.club вы найдете множество новинок, которые стоит прочитать.

Название:
QNX/UNIX: Анатомия параллелизма
Издательство:
-
ISBN:
-
Год:
-
Дата добавления:
16 сентябрь 2019
Количество просмотров:
361
Читать онлайн
Олег Цилюрик - QNX/UNIX: Анатомия параллелизма

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

Олег Цилюрик - QNX/UNIX: Анатомия параллелизма - описание и краткое содержание, автор Олег Цилюрик, читайте бесплатно онлайн на сайте электронной библиотеки mybooks.club
Книга адресована программистам, работающим в самых разнообразных ОС UNIX. Авторы предлагают шире взглянуть на возможности параллельной организации вычислительного процесса в традиционном программировании. Особый акцент делается на потоках (threads), а именно на тех возможностях и сложностях, которые были привнесены в технику параллельных вычислений этой относительно новой парадигмой программирования. На примерах реальных кодов показываются приемы и преимущества параллельной организации вычислительного процесса. Некоторые из результатов испытаний тестовых примеров будут большим сюрпризом даже для самых бывалых программистов. Тем не менее излагаемые техники вполне доступны и начинающим программистам: для изучения материала требуется базовое знание языка программирования C/C++ и некоторое понимание «устройства» современных многозадачных ОС UNIX.В качестве «испытательной площадки» для тестовых фрагментов выбрана ОСРВ QNX, что позволило с единой точки зрения взглянуть как на специфические механизмы микроядерной архитектуры QNX, так и на универсальные механизмы POSIX. В этом качестве книга может быть интересна и тем, кто не использует (и не планирует никогда использовать) ОС QNX: программистам в Linux, FreeBSD, NetBSD, Solaris и других традиционных ОС UNIX.

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

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

Существует несколько функций API, относящихся к службе глобальных имен: name_attach(), name_open() и name_close(). Программисты, знакомые с QNX 4, сразу «узнают» в них аналоги известных им функций qnx_name_attach(), qnx_name_open() и qnx_name_close(). Приложения используют эти функции для объявления имени службы, связи со службой и отсоединения от службы.

Итак, чтобы объявить свое имя глобально в сети, приложение-сервер должно на узле, где в режиме сервера функционирует менеджер службы глобальных имен, объявить свою службу, выполнив вызов:

if (!(NameServer = name_attach(NULL, "MyService", NAME_FLAG_ATTACH_GLOBAL)))

 return EXIT_FAILURE;

Флаг NAME_FLAG_ATTACH_GLOBAL указывает, что приложение-сервер объявляет свое имя глобально — в сети. Приложение, которое может подсоединить службу глобально, должно иметь право доступа root. После выполнения этого вызова в директории /dev/name/global появится подсоединенное имя MyService (если бы третий аргумент вызова был установлен в ноль, это имя оказалось бы подсоединенным к /dev/name/local и было бы доступно только локально).

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

• _NTO_CHF_UNBLOCK — доставлять владельцу канала импульс с кодом _PULSE_CODE_UNBLOCK и значением rcvid каждый раз, когда Reply-блокированный клиент попытается разблокироваться (скажем, по получению сигнала или по таймеру);

• _NTO_CHF_DISCONNECT — доставлять владельцу канала импульс с кодом _PULSE_CODE_DISCONNECT, когда от процесса отсоединились все установленные соединения клиента (клиент выполнил name_close() на каждый свой name_open() к имени сервера либо вообще умер);

• _NTO_CHF_COID_DISCONNECT — доставлять владельцу канала импульс с кодом _PULSE_CODE_COIDDEATH и значением coid (идентификатора соединения) для каждого соединения по этому каналу, когда канал закрывается.

Теперь, после создания канала, сервер может становиться на прием сообщений от клиентов:

rcvid = MsgReceive(NameServer->chid, &MsgBuf, sizeof MsgBuf);

Однако может так случиться, что клиент пошлет не непосредственное сообщение для сервера, а выполнит, скажем, чтение, что, по сути, тоже является отосланным сообщением. Поэтому при получении сообщений необходимо производить их «фильтрацию»:

if (MsgBuf.hdr_type >= _IO_BASE && Buffer.hdr.type <= _IO_MAX) {

 MsgError(rcvid, ENOSYS);

 continue;

}

Получив от клиента некое предопределенное сообщение, сервер сбрасывает флаг flagWork и выходит из петли ожидания сообщений, тем самым завершая свою работу.

С учетом этих деталей и организован нижеописанный сервер.

Код процесса-сервера, использующего службу глобальных имен

#include <stdio.h>

#include <errno.h>

#include <stdlib.h>

#include <sys/dispatch h>


/* На сервер могут приходить и импульсы. Как минимум. */

typedef struct _pulse msg_header_t;


/* Структура сообщения состоит из заголовка и буфера наших данных */

typedef struct _MsgBuf {

 msg_header_t hdr;

 char* Buffer;

} MsgBuf_t;


int main() {

 name_attach_t* NameServer;

 MsgBuf_t MsgBuf;

 int rcvid;

 char BufReply[100];

 int flagWork = 1;

 /* Создаем глобальное имя /dev/name/global/MyService */

 if (!(NameServer = name_attach(NULL, "MyService",

  NAME_FLAG_ATTACH_GLOBAL)))

  return EXIT_FAILURE;

 /* Становимся на петлю получения сообщений */

 while (flgWork) {

  if ((rcvid = MsgReceive(NameServer->chid, &MsgBuf,

   sizeof MsgBuf, NULL)) == -1) {

   printf("Ошибка при получении сервером MyService "

    "сообщения от клиентаn");

   fflush(stdout);

   break;

  }

  if (!rcvid) {

   // Получен импульс

   switch(MsgBuf.hdr.code) {

   case _PULSE_CODE_DISCONNECT:

    /* Поскольку для канала установлен флаг _NTO_CHF_DISCONNECT, ядро

       автоматически не освобождает связи, установленные клиентом ранее.

       Сервер должен выполнить это со своей стороны сам, "сознательно"

       удалив маршрут от себя обратно к клиенту */

    ConnectDetach(MsgBuf.hdr.scoid);

    break;

   case _PULSE_CODE_UNBLOCK;

    /* Клиент пытается разблокироваться, не дождавшись ответа по Reply. Надо

       выполнить какие-то действия, чтобы корректно (для себя)

       обработать эту ситуацию, и все-таки отпустить этого клиента - ему

       ведь надо! При этом импульсе в MsgBuf.hdr.value приходит rcvid */

    MsgReply(MsgBuf.hdr.value.sival_int, EAGAIN, NULL, 0);

    break;

   default:

    break;

   }

   continue;

   // вновь уходим на петлю приема сообщений

  }

  /* Полученное сообщение находится в диапазоне системных сообщений

     ввода/вывода. Не обрабатываем. */

  if (MsgBuf.hdr.type >= _IO_BASE && MsgBuf.hdr.type <= _IO_MAX) {

   MsgError(rcvid, ENOSYS);

   continue;

  }

  /* А вот это - сообщение для сервера. Обрабатываем. */

  if (MsgBuf.hdr.type <= 0x50001 || MsgBuf.hdr.type >= 0x500ff) {

   printf("Сервер получил сообщение неизвестно от"

    " кого с меткой %#xn", MsgBuf.hdr.type);

   strcpy(BufReply, "а кто это???");

  } else {

   printf("Сервер получил сообщение. "%s"n",

    MsgBuf.Buffer);

   strcpy(BufReply, "а, это ты, клиент");

  }

  MsgReply(rcvid, EOK, BufReply, strlen(BufReply) + 1);

 }

 // Конец петли получения сообщений

 /* Отсоединяемся от службы глобальных имен */

 name_detach(NameServer, 0);

 return EXIT_SUCCESS;

}

Приложения-клиенты, которым надо использовать глобальную службу имен, могут использовать функцию API name_open(). В случае, когда служба обеспечивается несколькими серверами (интересная и очень полезная возможность, заключающаяся в том, что несколько серверов вправе на различных узлах сети объявить одну и ту же службу), правила связи со службой имен таковы:

• Если поставщик службы имеется на том же узле, что и приложение, запросившее службу, менеджер пытается связать приложение прежде всего с локальным поставщиком. Если связь успешна, приложение общается со своим поставщиком локально, что обеспечивает лучшую производительность.

• Если локальный поставщик отсутствует или по каким-то причинам отказывает в поставке службы, менеджер пытается связать приложение с другими поставщиками. Если имеется несколько удаленных поставщиков, то порядок, в котором производятся попытки установить с ними связь (т.е. кто получит связь первым), не определен.

Код процесса-клиента, использующего службу глобальных имен

#include <stdio.h>

#include <errno.h>

#include <stdlib.h>

#include <sys/dispatch.h>


/* На сервер могут приходить и импульсы. Как минимум. */

typedef struct _pulse msg_header_t;


/* Структура сообщения состоит из заголовка и буфера наших данных */

typedef struct _MsgBuf {

 msg_header_t hdr;

 char* Buffer;

} MsgBuf_t;


int main() {

 MsgBuf_t MsgBuf;

 int fd;

 char BufReply[100];

 if ((fd = name_open("MyService", NAME_FLAG_ATTACH_GLOBAL)) == -1) {

  printf("Клиенту не удалось присоединиться к"

   " сервисуn");

  fflush(stdout);

  return EXIT_FAILURE;

 }

 // Инвентаризационная метка данного клиента

 MsgBuf.hdr.type = 0x50001;

 MsgBuf.hdr.subtype = 0x00;

 strcpy (MsgBuf.Buffer, "Здравствуй, дорогой сервер!");

 if (MsgSend(fd, &MsgBuf, sizeof MsgBuf, BufReply, sizeof BufReply) == -1) {

  printf("Клиент имеет проблемы с передачей сообщений"

   " серверуn");

  fflush(stdout);

  name_close(fd);

  return EXIT_FAILURE;

 }

 printf("Клиент получил от сервера такой ответ: "

  ""%s" n", BufReply);

 name_close(fd);

 return EXIT_SUCCESS;

}

Тем, кто уже использовал функции работы со службой глобальных имен в предыдущей реализации ОС QNX 6.2 (где, как указывалось выше, она уже существовала, но могла функционировать только локально), следует обратить внимание, что в поведении этих функций появились небольшие изменения.

Раньше, когда приложение-клиент использовало вызов функции name_open() для связи с сервером, сервер об этом не знал. Теперь это изменено: серверу фактически отсылается сообщение _IO_CONNECT/_IO_OPEN. Кроме того, изменено приложение-сервер, чтобы иметь возможность обрабатывать приход сообщения _IO_CONNECT.


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

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


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

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

Прокомментировать
Подтвердите что вы не робот:*
Подтвердите что вы не робот:*
Все материалы на сайте размещаются его пользователями.
Администратор сайта не несёт ответственности за действия пользователей сайта..
Вы можете направить вашу жалобу на почту librarybook.ru@gmail.com или заполнить форму обратной связи.