Операционная система реального времени

Автор: Пользователь скрыл имя, 12 Декабря 2011 в 21:38, реферат

Краткое описание

QNX - этo зарeгистрированная тoргoвая марка фирмы QNX (Quantum) Software Systems, Canada. Фирма oснoвана в 1980 гoду. В тo жe врeмя QNX - этo oпeрациoнная систeма (ОС) стандарта POSIX, кoтoрая пoзвoляeт oбeспeчить на пeрсoнальнoм кoмпьютeрe распрeдeлeнную oбрабoтку данных в рeальнoм масштабe врeмeни. ОС QNX oбладаeт такими вoзмoжнoстями, кoтoрые стандартные UNIX-системы мoгут тoлькo надеяться дoстигнуть. QNX стала первoй кoммерческoй oперациoннoй системoй, кoтoрая пoзвoлила испoльзoвать передачу сooбщений в качестве oснoвнoгo средства взаимoдействия между прoцессами (IPC). Мoщнoсть, прoстoта и элегантнoсть QNX дoстигается благoдаря пoстрoению всей системы на базе технoлoгии IPC с передачей сooбщений.

Файлы: 1 файл

Курсовая по операционным.docx

— 290.99 Кб (Скачать)


         

 Использование Send(), Receive() и Reply()
          Давайте теперь более подробно рассмотрим вызовы функций Send(), Receive() и Reply(). Воспользуемся рассмотренным выше примером передачи сообщения от процесса A к процессу B. 

          Функция Send() 
          Предположим, что процесс А выдает запрос на передачу сообщения процессу В.Это выполняется посредством вызова функции Send( ). 
          Send( pid, smsg, rmsg, smsg_len, rmsg_len ) 
          При вызове функции Send() используются следующие аргументы:

Pid - идентификатор процесса(process ID), которому предназначается сообщение(т.е. процесса B); этот идентификатор используется для обращения к процессу со стороны операционной системы и других процессов.

Smsg - буфер сообщения(т.е. сообщение, подлежащее посылке).

Rmsg - буфер ответа(будет содержать ответ от процесса B).

Smsg_len - длина посылаемого сообщения в байтах.

Rmsg_len - максимальная длина ответа, который может принять процесс A, в байтах. 
          Обратите внимание, что будет передано не более smsg_len байт и не более чем rmsg_len байт будет получено в качестве ответа - это гарантирует, что не произойдет случайного переполнения буферов. 

          Функция Receive() 
          Вызвав запрос Receive(), процесс B может получить сообщение, направленное ему процессом A.
          Receive( Pid,0, msg, msg_len ) 
          Вызов функции Receive() содержит следующие аргументы:

Pid - идентификатор процесса, который послал сообщение (т.е. процесс A).

0(ноль) - означает, что процесс B желает принять сообщение от любого процесса.

Msg - буфер, куда будет помещено принимаемое сообщение.
          Если значения аргументов smsg_len в вызове функции Send() и msg_len в вызове функции Receive() отличаются, друг от друга, то наименьшее из них определяет размер данных, которые будут переданы. 

          Функция Reply() После успешного получения сообщения от процесса A, процесс B должен ответить процессу A, вызвав функцию Reply().
          Reply( pid, reply, reply_len )
Вызов функции Reply() содержит следующие аргументы:

Pid - идентификатор процесса, которому предназначается ответ (т.е. процесс A).

Reply - буфер, содержащий ответ.

Reply_len - длина данных, передаваемых в качестве ответа, в байтах. 
          Если значения аргументов reply_len при вызове функции Reply() и rmsg_len при вызове функции Send() отличаются друг от друга, то наименьшее из них определяет размер передаваемых данных. 

          Reply-управляемый обмен сообщениями 
          Пример обмена сообщениями, который мы только что рассмотрели, иллюстрирует наиболее распространенный случай использования сообщений - случай, когда для процесса, выполняющего функции сервера, нормальным является состояние RECEIVE-блокирован в ожидании каких-либо запросов клиента. Это называется send-управляемый обмен сообщениями: процесс-клиент инициирует действие, посылая сообщения, ответ сервера на сообщение завершает действие. 
          Существует и другая модель обмена сообщениями, не столь распространенная, как рассмотренная выше, хотя в некоторых ситуациях она даже более предпочтительна: reply-управляемый обмен сообщениями, при котором действие инициируется вызовом функции Reply(). В этом случае процесс-"работник" посылает серверу сообщение, говорящее о том, что он готов к работе. Сервер не отвечает сразу, а "запоминает", что работник готов выполнить его задание. В последствии сервер может инициировать действие, ответив ожидающему задание работнику. Процесс-работник выполнит задание и завершит действие, послав серверу сообщение, содержащее результаты своей работы. 


          Дополнительные сведения 
          При разработке программ, использующих передачу сообщений, необходимо иметь в виду следующее:

Cообщение сохраняется в теле посылающего процесса до тех пор, пока принимающий процесс не будет готов получить его. Сообщение не копируется в Микроядро. Это безопасно, т.к. посылающий процесс SEND-блокирован и не может неумышленно изменить содержимое сообщения.

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

При посылке сообщения процессу не требуется знать состояние того процесса, которому это сообщение адресовано. Если получатель не готов к приему сообщения в момент его отправки, то посылающий сообщение процесс просто становится SEND-блокирован.

Если это необходимо, то процесс может посылать сообщение нулевой длины, ответ нулевой длины, либо и то и другое.

С точки зрения разработчика, использование Send() для передачи процессу-серверу запроса на получение какой-либо услуги равнозначно вызову библиотечной подпрограммы, предоставляющей ту же самую услугу. В обоих случаях ваша программа сначала подготавливает определенные данные, а затем вызывает либо функцию Send(), либо библиотечную подпрограмму, после чего ожидает, когда они закончат выполнение. В обоих случаях код, реализующий запрашиваемую услугу, выполняется между двумя четко определенными точками - Receive() и Reply() для процесса-сервера, входом в подпрограмму и командой return для вызова библиотечной подпрограммы. Когда вызываемая сервисная программа завершена, ваша программа "знает", куда помещены результаты, и может приступить к проверке возвращенного кода ошибки, обработке результатов и так далее. 
          Несмотря на такую кажущуюся простоту, вызов функции Send() делает гораздо больше, чем простой вызов библиотечной подпрограммы. Функция Send() может прозрачно для вызывающей программы передать запрос на другой узел сети, где и будет в действительности выполняться обслуживающий запрос код. При этом также может быть задействована параллельная обработка данных без издержек на создание нового процесса. Процесс-сервер может сразу, как только станет возможным, вызвать функцию Reply(), позволяя тем самым запрашивавшему процессу возобновить выполнение и, в то же время, продолжить выполнение самому.         

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

 

          
 

Сервер получил сообщение от клиента A и клиента B (но еще не ответил им). Сообщения от клиентов C, D, E еще не получены. К содержанию 

          Дополнительные возможности
QNX также предоставляет следующие дополнительные возможности по передаче сообщений:

         Условный прием сообщений 

         Чтение или запись части сообщений 

         Составные сообщения (сообщения, состоящие из нескольких частей) 



Условный прием сообщений


          Обычно, когда процесс хочет принять сообщение, он вызывает функцию Receive() для ожидания прихода сообщения. Это обычный способ получения сообщений, который пригоден в большинстве случаев.
          Однако возможна ситуация, когда процессу необходимо определить, имеются ли ожидающие приема сообщения, не попадая при этом в состояние RECEIVE-блокирован в случае их отсутствия. Например, процессу требуется опрашивать работающее с высокой скоростью устройство, которое не способно генерировать прерывание, и в то же время он должен отвечать на сообщения от других процессов. В этом случае процесс может использовать функцию Creceive(), которая либо прочитает ожидающее приема сообщение, либо немедленно вернет управление процессу в случае отсутствия ожидающих приема сообщений. 



Чтение или запись части сообщений 

         Иногда желательно читать или записывать сообщения по частям с тем, чтобы использовать уже выделенный для сообщения буфер вместо выделения отдельного рабочего буфера.
          Например, менеджер ввода/вывода может принимать данные в виде сообщений, которые состоят из заголовка фиксированной длины и следующих за ним данных переменной длины. В заголовке указывается размер данных (от 0 до 64 Кбайт). В этом случае менеджер ввода/вывода может сначала принять только заголовок сообщения, а затем использовать функцию Readmsg() для чтения данных переменной длины непосредственно в соответствующий буфер вывода. Если размер данных превышает размер буфера, то менеджер может неоднократно вызывать функцию Readmsg() по мере освобождения буфера вывода. Аналогичным образом, функция Writemsg() может быть использована для поэтапного копирования данных в выделенный для ответного сообщения буфер непосредственно в теле процесса, пославшего сообщение, уменьшая, таким образом, потребность менеджера ввода/вывода в выделении внутренних буферов. 



Составные сообщения  

         До сих пор мы рассматривали сообщения как непрерывную последовательность байт. Однако сообщения часто состоят из двух или более отдельных частей. Например, сообщение может иметь заголовок фиксированной длины, за которым следуют данные переменной длины. Для того чтобы избежать копирования частей такого сообщения во временные промежуточные буферы при передаче или приеме, может быть использовано составное сообщение, состоящее из двух или более отдельных буферов сообщений. Именно благодаря этой возможности менеджеры ввода/вывода QNX, такие как Dev и Fsys, достигают своей высокой производительности. 
          Следующие функции позволяют обрабатывать составные сообщения:

Creceivemx( )

Readmsgmx( )

Receivemx( )

Replymx( )

Sendmx( )

Writemsgmx( )

 

        

 Составные сообщения могут быть описаны с помощью специальной mx структуры. Микроядро объединяет части такого сообщения в единый непрерывный поток данных. 

          Зарезервированные коды сообщений 
          QNX начинает все сообщения с 16-ти битного слова, называемого кодом сообщения. Заметим, однако, что это не является обязательным для вас требованием при написании собственных программ. QNX использует коды сообщений в следующих диапазонах: 

IPC посредством прокси


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

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

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

Обработчик прерывания хочет известить процесс о поступлении новых данных. 
          Для создания прокси используется функция языка Си qnx_proxy_attach(). Любой другой процесс или обработчик прерывания, которому известен идентификатор прокси, может воспользоваться функцией языка Си Trigger() для того, чтобы заставить прокси передать заранее заданное сообщение. Запрос Trigger() обрабатывается Микроядром.
          Прокси может быть "запущено" неоднократно - каждый раз при этом оно посылает сообщение. Прокси может накапливать очередь длиной до 65535 сообщений.


        

   Процесс-клиент запускает прокси 3 раза, в результате чего сервер получает 3 "консервированных" сообщения от прокси. 


IPC посредством сигналов


          Сигналы являются традиционным способом асинхронной связи, которая используется в течение многих лет в различных операционных системах.
          QNX поддерживает большой набор сигналов, соответствующих стандарту POSIX, кроме того, сигналы, исторически присущие некоторым UNIX-системам, и ряд сигналов, уникальных для QNX. 
          Как породить сигнал
          Считается, что сигнал доставлен процессу тогда, когда выполняется определенное в процессе для данного сигнала действие. Процесс может посылать сигнал самому себе. 
          Получение сигналов
          Процесс может принять сигнал одним из трех способов, в зависимости от того, как в процессе определена обработка сигналов:

Если процесс не определил никаких специальных мер по обработке сигнала, то выполняется предусмотренное для сигнала действие по умолчанию - обычно таким действием по умолчанию является завершение работы процесса.

Процесс может игнорировать сигнал. Если процесс игнорирует сигнал, то сигнал не оказывает на процесс никакого воздействия (учтите, что SIGCONT, SIGSTOP и SIGKILL не могут быть игнорированы в обычных обстоятельствах).

Процесс может предусмотреть обработчик сигнала - функцию, которая будет вызываться при приеме сигнала. Если процесс содержит обработчик для какого-либо сигнала, говорят, что процесс может "поймать" этот сигнал. Любой процесс, который "ловит" сигнал, фактически получает особый вид программного прерывания. Никакие данные с сигналом не передаются. 
          В промежутке времени между моментом, когда сигнал порожден, и моментом, когда он доставлен, сигнал называется ожидающим. Для процесса ожидающими одновременно могут быть несколько различных сигналов. Сигналы доставляются процессу, когда планировщик ядра делает этот процесс готовым к выполнению. Процесс не должен строить никаких предположений относительно порядка, в котором будут доставлены ожидающие сигналы. 
          Управление обработкой сигналов 
          Чтобы задать желаемый способ обработки для каждого из сигналов, вы можете использовать функции языка Си signal() стандарта ANSI или sigaction() стандарта POSIX. 
          Функция sigaction() предоставляет большие возможности по управлению обработкой сигналов.
          Вы можете изменить способ обработки сигнала в любой момент времени. Если вы укажете, что сигнал данного типа должен игнорироваться, то все ждущие сигналы такого типа будут немедленно отброшены. 
          Обработчики сигналов 
          Некоторые специальные замечания касаются процессов, которые ловят сигналы посредством обработчиков сигналов. 
          Вызов обработчика сигнала аналогичен программному прерыванию. Он выполняется асинхронно по отношению к остальной части процесса. Таким образом, существует вероятность того, что обработчик сигнала будет вызван во время выполнения любой из имеющихся в программе функций (включая библиотечные функции). 
          Если в вашей программе не предусмотрен возврат из обработчика сигнала, то могут быть использованы функции siglongjmp() либо longjmp() языка Си, однако, функция siglongjmp() предпочтительнее. При использовании функции longjmp() сигнал остается блокированным. 
          Блокирование сигналов 
          Иногда может возникнуть необходимость временно запретить получение сигнала, не изменяя метод его обработки. QNX предоставляет набор функций, которые позволяют блокировать получение сигналов. Блокированный сигнал остается ожидающим; после разблокирования он будет доставлен вашей программе.
          Пока ваша программа выполняет обработчик сигнала для определенного типа сигнала, QNX автоматически блокирует этот сигнал. Это означает, что нет необходимости заботиться о вложенных вызовах обработчика сигнала. Каждый вызов обработчика сигнала - это неделимая операция по отношению к доставке следующих сигналов этого типа. Если ваш процесс выполняет нормальный возврат из обработчика, сигнал автоматически разблокируется. 
          Сигналы и сообщения 
          Существует важное взаимодействие между сигналами и сообщениями. Если ваш процесс SEND-блокирован или RECEIVE-блокирован в момент получения сигнала, и вы предусмотрели обработчик сигнала, происходят следующие действия: 


Информация о работе Операционная система реального времени