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

Роб Кёртен - Введение в QNX/Neutrino 2. Руководство по программированию приложений реального времени в QNX Realtime Platform

На сайте mybooks.club вы можете бесплатно читать книги онлайн без регистрации, включая Роб Кёртен - Введение в QNX/Neutrino 2. Руководство по программированию приложений реального времени в QNX Realtime Platform. Жанр: Программное обеспечение издательство -,. Доступна полная версия книги с кратким содержанием для предварительного ознакомления, аннотацией (предисловием), рецензиями от других читателей и их экспертным мнением.
Кроме того, на сайте mybooks.club вы найдете множество новинок, которые стоит прочитать.

Название:
Введение в QNX/Neutrino 2. Руководство по программированию приложений реального времени в QNX Realtime Platform
Автор
Издательство:
-
ISBN:
-
Год:
-
Дата добавления:
16 сентябрь 2019
Количество просмотров:
350
Читать онлайн
Роб Кёртен - Введение в QNX/Neutrino 2. Руководство по программированию приложений реального времени в QNX Realtime Platform

Роб Кёртен - Введение в QNX/Neutrino 2. Руководство по программированию приложений реального времени в QNX Realtime Platform краткое содержание

Роб Кёртен - Введение в QNX/Neutrino 2. Руководство по программированию приложений реального времени в QNX Realtime Platform - описание и краткое содержание, автор Роб Кёртен, читайте бесплатно онлайн на сайте электронной библиотеки mybooks.club
Книга "Введение в QNX/Neutrino 2» откроет перед вами в мельчайших подробностях все секреты ОСРВ нового поколения от компании QNX Software Systems Ltd (QSSL) — QNX/Neutrino 2. Книга написана в непринужденной манере, легким для чтения и понимания стилем, и поможет любому, от начинающих программистов до опытных системотехников, получить необходимые начальные знания для проектирования надежных систем реального времени, от встраиваемых управляющих приложений до распределенных сетевых вычислительных системВ книге подробно описаны основные составляющие ОС QNX/Neutrino и их взаимосвязи. В частности, уделено особое внимание следующим темам:• обмен сообщениями: принципы функционирования и основы применения;• процессы и потоки: базовые концепции, предостережения и рекомендации;• таймеры: организация периодических событий в программах;• администраторы ресурсов: все, что относится к программированию драйверов устройств;• прерывания: рекомендации по эффективной обработке.В книге представлено множество проверенных примеров кода, подробных разъяснений и рисунков, которые помогут вам детально вникнуть в и излагаемый материал. Примеры кода и обновления к ним также можно найти на веб-сайте автора данной книги, www.parse.com.

Введение в QNX/Neutrino 2. Руководство по программированию приложений реального времени в QNX Realtime Platform читать онлайн бесплатно

Введение в QNX/Neutrino 2. Руководство по программированию приложений реального времени в QNX Realtime Platform - читать книгу онлайн бесплатно, автор Роб Кёртен

Поскольку мы возвращаем данные от устройства, мы знаем, что к устройству производился доступ. Мы устанавливаем биты IOFUNC_ATTR_ATIME и IOFUNC_ATTR_DIRTY_TIME в поле flags атрибутной записи. Это служит напоминанием для функции io_stat() о том, что время доступа стало недействительным, и перед выполнением ответа его следует скорректировать по системным часам. Если бы нам очень хотелось, мы могли бы записать текущее время в поле atime атрибутной записи и сбросить флаг IOFUNC_ATTR_DIRTY_TIME; однако, это было бы не очень-то эффективно, поскольку мы предполагаем получить от клиента значительно большее запросов типа read(), чем запросов типа stat(). Впрочем, ваши условия могут диктовать иначе.

Так какое же время видит клиент, когда он вызывает-таки функцию stat()? Функция iofunc_stat_default(), предоставляемая библиотекой администратора ресурсов, посмотрит на поле flags атрибутной записи, чтобы проверить, являются времена доступа (поля atime, ctime и mtime) корректными или нет. Если нет (как это было бы после вызова io_read() с возвратом данных), iofunc_stat_default() устанавливает нужные из них в значение текущего времени.

Этап 7

Теперь мы увеличиваем смещение lseek() на число возвращенных клиенту байт, но делаем это только в том случае, если не обрабатываем модификатор _IO_XTYPE_OFFSET. Это гарантирует, что в случае отсутствия флага _IO_XTYPE_OFFSET, если клиент вызовет функцию lseek() для определения текущей позиции, или (более важный случай) если клиент вызовет read() для чтения еще нескольких байт, смещение в ресурсе будет корректным. Если _IO_XTYPE_OFFSET установлен, мы оставляем содержащееся в ocb смещение в покое.

Этап 8

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

Этап 9

И наконец, на этапе 9 мы выполняем действия, не зависящие от того, возвращаем мы данные клиенту или нет. Поскольку мы уже сами разблокировали клиента при помощи MsgReply(), мы, конечно же, не хотим, чтобы это попыталась сделать еще и библиотека администратора ресурсов. Поэтому мы сообщаем ей, что мы уже сделали это сами, возвратом _RESMGR_NOREPLY.

Эффективное применение других функций обмена сообщениями

Как вы помните из главы «Обмен сообщениями», мы упоминали еще несколько функций обмена сообщениями, а именно — функции MsgWrite(), MsgWritev() и MsgReplyv(). Повод, в связи с которым я снова упоминаю здесь эти функции, состоит в том, что ваша функция io_read() может быть превосходным местом для их применения. В простом примере, показанном выше, мы возвращали непрерывный массив данных из постоянного места в памяти. В реальной же жизни вам может понадобиться возвратить, скажем, множество фрагментов данных из различных выделенных вами буферов. Классическим примером такого случая является циклический буфер, который часто применяется, например, в драйверах последовательных устройств. Часть данных может быть размещена в конце буфера, другая часть — в начале. В этом случае для возврата обеих частей данных вам понадобилось бы передать MsgReplyv() двухэлементный вектор ввода/вывода (IOV), где первый элемент содержал бы адрес (и длину) «нижней» части данных, а второй — адрес (и длину) «верхней» части. Или же, если вы ожидаете прибытия данных частями, вы могли бы вместо этого использовать функции MsgWrite() или MsgWritev() для записи данных в адресное пространство клиента по мере их поступления, а затем выдать заключительный вызов MsgReply() или MsgReplyv(), чтобы разблокировать клиента. Как мы уже показали выше, функция MsgReply() может и не передавать никаких данных— вы можете использовать ее просто для того, чтобы разблокировать клиента.

Простой пример функции io_write()

Это был простой пример функции io_read(); давайте теперь перейдем к функции io_write(). Основной камень преткновения, связанный с io_write(), — получить доступ к данным. Поскольку библиотека администратора ресурсов считывает лишь незначительную часть сообщения от клиента, переданные клиентом данные (они идут сразу после заголовка _IO_WRITE) могут быть приняты функцией io_write() только частично. Простой пример — представьте себе клиента, записывающего один мегабайт. Библиотекой администратора ресурсов будут считаны только заголовок сообщения и несколько байт данных. Остальная часть мегабайта остается по-прежнему доступной на клиентской стороне — администратор ресурсов при желании может к ней обращаться.

Реально рассмотрения заслуживают только два случая:

• все содержимое сообщения клиентской функции write() было считано библиотекой администратора ресурсов полностью; или

• этого не произошло.

Судьбоносное решение, однако, состоит в ответе на следующий вопрос: «Какие проблемы сопряжены с попыткой сохранить полученную с первым сообщением часть данных?» Ответ такой: овчинка не стоит выделки. Тому есть ряд причин:

• обмен сообщениями (операции копирования на уровне ядра) выполняется очень быстро;

• проверка, получены ли данные целиком или частично, влечет определенные накладные расходы;

• дополнительные накладные расходы связаны с попыткой «сохранения» первой, уже прибывшей, части данных, в свете того факта, что ожидаются дополнительные.

По-моему, первые два пункта говорят сами за себя. Третий же пункт заслуживает пояснения. Давайте предположим, что клиент переслал большую порцию данных, и мы приняли-таки решение о том, что было бы неплохо попробовать сохранить ту часть данных, которая уже получена. К сожалению, эта часть оказалось очень небольшой. Это означает, что вместо одного непрерывного массива байт у нас теперь будет большой кусок и маленький «довесок». Иными словами, только ради этого маленького кусочка нам придется значительно усложнять работу с данными, что может неприятно сказаться на эффективности кода. Это потенциальная головная боль, не делайте так!

Реальным ответом на поставленный вопрос будет просто заново считать данные в заранее подготовленные буферы. В нашем простом примере функции io_write() я буду просто каждый раз выделять буфер при помощи malloc(), считывать в него данные, а затем освобождать его функцией free(). Разумеется, есть и куда более эффективные способы выделения буферов и управления ими!

Еще один тонкий момент в этом примере функции io_write() — это обработка модификатора _IO_XTYPE_OFFSET (и связанных с этим данных; здесь она выполняется несколько иначе, чем в примере io_read()).

/*

 * io_write1.c

*/

#include <stdio.h>

#include <stdlib.h>

#include <errno.h>

#include <sys/neutrino.h>

#include <sys/iofunc.h>


void process_data(int offset, void *buffer, int nbytes) {

 // Сделать что-нибудь с данными

}


int io_write(resmgr_context_t *ctp, io_write_t *msg,

 iofunc_ocb_t *ocb) {

 int sts;

 int nbytes;

 int off;

 int start_data_offset;

 int xtype;

 char *buffer;

 struct _xtype_offset *xoffset;


 // Проверить, открыто ли устройство на запись

 if ((sts =

  iofunc_write_verify(ctp, msg, ocb, NULL)) != EOK) {

  return (sts);

 }


 // 1) Проверить и обработать переопределение

 XTYPE xtype = msg->i.xtype & _IO_XTYPE_MASK;

 if (xtype == _IO_XTYPE_OFFSET) {

  xoffset = (struct _xtype_offset*)(&msg->i + 1);

  start_data_offset = sizeof(msg->i) + sizeof(*xoffset);

  off = xoffset->offset;

 } else if (xtype == _IO_XTYPE_NONE) {

  off = ocb->offset;

  start_data_offset = sizeof(msg->i);

 } else {

  // Неизвестный тип; игнорировать

  return (ENOSYS);

 }


 // 2) Выделить достаточно большой буфер для данных

 nbytes = msg->i.nbytes;

 if ((buffer = malloc(nbytes)) == NULL) {

  return (ENOMEM);

 }


 // 3) Считать данные от клиента (возможно, повторно)

 if (resmgr_msgread(ctp, buffer, nbytes,

  start_data_offset) == -1) {

  free(buffer);

  return (errno);

 }


 // 4) Сделать что-нибудь с данными

 process_data(off, buffer, nbytes);


 // 5) Освободить память буфера

 free(buffer);


 // 6) Установить, сколько байт должна возвращать


Роб Кёртен читать все книги автора по порядку

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


Введение в QNX/Neutrino 2. Руководство по программированию приложений реального времени в QNX Realtime Platform отзывы

Отзывы читателей о книге Введение в QNX/Neutrino 2. Руководство по программированию приложений реального времени в QNX Realtime Platform, автор: Роб Кёртен. Читайте комментарии и мнения людей о произведении.

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