Архитектура Аудит Военная наука Иностранные языки Медицина Металлургия Метрология
Образование Политология Производство Психология Стандартизация Технологии


Операционная система QNX . Системная архитектура.



План лекции.

1. Связь между процессами (IPC)

2. IPC посредством messages

3. Обмен сообщениями управляемый ответами

4. Продвинутые возможности по передачи сообщений.

5. Зарезервированные коды сообщений

 

QNX Kernel отвечает за осуществление следующих функций:

• связь между процессами— Kernel занимается роутингом messages; он так же управляет двумя другими формами IPC—proxies и Signals

• низкоуровневая сетевая связь— Kernel доставляет все сообщения, предназначенные для процессов на других нодах

• построение очереди процессов— Kernel scheduler решает, какой процесс будет выполняться следующим

• обработка прерываний на первом уровне – все аппаратные прерывания и ошибки сначала направляются через Kernel, затем передаются соответствующему драйверу или System manager

ПРОЦЕССЫ

 

                                             ПРЕРЫВАНИЯ

Рис. QNX Microkernel.

 

1. Связь между процессами (IPC)

QNX Kemel поддерживает три необходимых вида связи между процессами: messages, proxies, и Signals.

Messages это основная форма IPC в QNX. Они обеспечивают синхронную связь между кооперирующими процессами, где процесс, посылающий сообщение требует подтверждения приема и возможно ответ на это сообщение.

Proxies -- это особая форма сообщений. Они особенно хорошо подходят для сообщений о событиях, где процесс-отправитель не требует взаимодействия с процессем-получателем.

Signals это традиционная форма IPC. Они нужны для поддержки несинхронной связи между процессами.

 

2. IPC посредством messages

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

 

Примитивы для передачи messages.

Для общения напрямую, кооперирующие процессы используют функции языка C:

• Send()—для посылки messages

• Receive()— для приема messages

• Reply()—для ответа процессам, которые послали messages

Эти функции могут быть использованы локально или в сети.

За исключением тех случаев, когда процессы хотят связываться напрямую, им не надо использовать Send(), Receive(), и Reply(). Библиотека QNX C построена поверх механизма сообщений — процессы используют этот механизм не на прямую, когда они используют стандартные возможности, такие как pipes.

Приведенный ниже пример отображает простейшую последовательность событий, в которой два процесса, А и В используют Send(), Receive(), и Reply() для связи друг с другом:

1) Процесс A посылает сообщение процессу B путем выдачи kernel-у запроса Send(). В этот момент процесс А становится заблокированным для дальнейших посылок сообщений до тех пор, пока процесс В не выдаст Receive() чтобы получить сообщение.

2) Процесс В выдает Receive() и получает ожидающее сообщение процесса А. Процесс А переходит в состояние "заблокирован для приема ответа". Процесс В не блокируется, так как это его ожидали.

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

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

 

Синхронизация процессов.

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

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

 

Заблокированные состояния.

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

В таблице приведены возможные заблокированные состояния процессов:

 

Если процесс выдал: то он:
Запрос Send(), и сообщение посланное им ещё не принято процессом-получателем   Запрос Send(), и сообщение было принято процессом-получателем, но он ещё не ответил   Запрос Receive(), но ещё не принял сообщения Заблокирован для передачи (SEND-blocked)   Заблокирован для приема ответа (REPLY-blocked)   Заблокирован для приема сообщения (RECEIVE-blocked)

 

Состояния возможные при передал-принял-ответил операции.

Send()  This process  Send()  Other process

 

 

Применение Send(), Receive(), и Reply()

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

 

1. Send() Пусть процесс A выдает запрос на посылку сообщения процессу В.

Выдача запроса происходит посредством вызова функции Send():

Send( pid, smsg, rmsg, smsg_len, rmsg_len);

Вызов Send() содержит следующие аргументы:

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

- smsg - буфер сообщения (посылаемое сообщение)

- rmsg - буфер ответа (тут будет ответ процесса В)

- smsg_len - длина посылаемого сообщения

- rmsg_len - максимальная длина ответа которую примет процесс А

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

 

2. Receive() Процесс В может принять Send() выданную процессом A путем вызова Receive():

pid = Receive (0, msg, msg Jen);

 

Вызов Receive() содержит следующие аргументы:

– pid - возвращается идентификатор процесса-отправителя (например Process A) (ноль) обозначает, что процесс В готов принимать сообщения от всех процессов

– msg - буфер, куда будет принято сообщение

– msg _len - максимальный объем информации, который может быть принят в буфер приема

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

 

3. Reply(). Успешно получив сообщение от процесса А, процесс В должен ответить процессу А вызвав функцию Reply():

Reply (pid, reply, reply_len);

Вызов Reply() содержит следующие аргументы:

– pid - идентификатор процесса, которому предназначен ответ (например Process A)

– reply - буфер ответа

– reply_len - объем передаваемой в качестве ответа информации

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

 

3. Обмен сообщениями управляемый ответами

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

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

Вот ещё несколько вещей, которые надо знать об обмене сообщениями:

· Содержание сообщения хранится в процессе отправителе до тех пор, пока получатель не будет готов обработать его. Сообщение НЕ КОПИРУЕТСЯ в Kernel. Это безопаснее, так как процесс-отправитель заблокирован на отправление и не может случайно исказить отправляемую информацию.

· Информация, передаваемая как ответ копируется из отвечающего процесса в процесс заблокированный на ответ как atomic операция когда выдан запрос Reply(). Reply() не блокирует отвечающий процесс—процесс заблокированный на ответ освобождается после того как информация скопирована на свое место.

· Для того чтобы послать сообщение отправляющему процессу не нужна информация о состоянии принимающего. Если принимающий процесс не готов получить уже посланное сообщение то процесс- отправитель просто блокируется на отправление.

· При необходимости могут быть посланы сообщения и ответы нулевой длины.

 

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

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

 

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

4. Продвинутые возможности по передачи сообщений.

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

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

• чтение или запись части сообщения

• сообщение из нескольких частей

 

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

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

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

Следует, если возможно, избегать использования Creceive(), поскольку она позволяет процессу занимать процессор постоянно со своим уровнем приоритета.

 

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

Иногда требуется читать или записывать только часть сообщения, чтобы таким образом использовать буфер уже отведенный для сообщения а не создавать отдельный рабочий буфер.

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

 

Сообщение из нескольких частей

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

Существуют следующие функции для работы с сообщениями из нескольких частей:

Creceivemx()

Readmsgmx()

Receivemx()

Replymx()

Sendmx()

Writemsgmx()

 

 


 

 

Сообщение из нескольких частей может быть описано с помощью mx control structure. Кernel собирает их в единый поток данных.

 

 

5. Зарезервированные коды сообщений

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

 

0X0000 to 0X0OFF  сообщения менеджера процессов
0X0100 to0x0IFF    I/O сообщения (общие для всех I/O серверов)
0X0200 toOx02FF Сообщения менеджера файловой системы
0X0300 to0x03FF Сообщения менеджера устройств
0X0400 to0x04FF Сообщения менеджера сети
0X0500 toOXOFFF Зарезервировано для будущих системных процессов Quantum

 

Лекция № 6.

Связь между процессами111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111имер111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 посредством proxies. Сигналы и сообщения.

План лекции.

1. IPC посредством proxies

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

3. Сигналы и сообщения.

 

1. IPC посредством proxies

Proxy - это форма не блокирующего сообщения, которая очень подходит для извещения о событиях, когда процесс-отправитель не собирается работать с получателем. Единственная функция proxy -- это посылать стандартные сообщения конкретному процессу, который владеет этим proxy. Так же как и предыдущий вид IPC -- сообщения (messages), proxy могут работать и по сети.

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

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

• Один процесс хочет послать другому некие данные, но не нуждается в ответе или в каком-либо другом подтверждении получения их.

• Обработчик прерываний хочет сообщить процессу, что появились данные для обработки.

Proxy создаются при помощи функции языка С qnx_proxy_attach(). Любой процесс (кроме родительского) или обработчик прерываний знающий идентификатор proxy может заставить proxy доставить его заранее определенное сообщение, используя функцию С Trigger(). Запросы Trigger() обрабатывает Kernel. Будем называть это активацией proxy.

Proxy может быть активирован многократно, и он будет посылать свое сообщение каждый раз, когда активирован. Длина очереди таких сообщений, которые надо доставить, может достигать 65,535.

client 3 2  1 proxy

"canned message" 3

"canned message" 2

"canned message" 1

server

Клиентский процесс активирует proxy три раза, что приводит к получению сервером трех "законсервированных сообщений" от proxy (типа шютка автора прим. пер.).

 

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

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

QNX поддерживает богатый набор POSIX-совместимых сигналов в добавления к специальным QNX сигналам и традиционным сигналам UNIX-оидных систем.

Считается, что сигнал дошел до процесса, когда тот предпринял какое-либо определенное действие в ответ на него. Процесс может так же сам послать сигнал.

Генерация сигналов

Если ты хочешь: то используй:
генерировать сигнал от оболочки                   kill или slay утилиты
генерировать сигнал изнутри процесса          kill() или raise() функции С

 

Получение сигналов

Процесс может получить сигнал одним из трех способов в зависимости от того, какие у него настройки:

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

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

· Процесс может иметь обработчик сигналов для полуученого сигнала— обработчик сигналов это функция в процессе, которая начинает работать по приходу сигнала. Когда у процесса есть обработчик сигналов для конкретного сигнала - говорят, что процесс способен "отловить" сигнал. Любой процесс "отловивший" сигнал в результате получает некий вид программного прерывания. С сигналом не передается никаких данных.

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

 

Обобщение сигналов

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

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

SIGABRT

SIGALRM

SIGFPE**

SIGHUP

SIGILL**

SIGINT

SIGKILL*

SIGPIPE

SIGQUIT

SIGSEGV**

SIGTERM

SIGUSR1

SIGUSR2

Отловить/ игнорировать Действие по умолчанию Описание
да Прекратить процесс Сигнал ненормального завершения, такой как выдает функция abort()
Да -"- Сигнал окончания времени такой как выдает alarm()
Да -"- Неправильная математическая операция (целое или с плав. точкой) типа деления на ноль или переполнение
Да -"- Смерть сессионного лидера (session leader), или отключение на контролирующем терминале
Да -"- Обнаружение ошибочной аппаратной инструкции
Да -"- Интерактивный сигнал внимания (<Break>)
Да -"- Сигнал завершения, должен выдаваться только чрезвычайными
Да -"- Попытка работать с pipe который никто не читает
Да -"- Интерактивный сигнал прекращения
Да -"- Обнаружение неправильной ссылки на память
Да -"- Сигнал прекращения
Да -"- Зарезервирован как сигнал для приложений номер 1
Да -"- Зарезервирован как сигнал для приложений номер 2
                                                                                                               

 

Сигналы для контроля за работой

Сигнал Отловить/ игнорировать Действие по умолчанию Описание
SIGCHLD     Да Игнорировать сигнал Дочерний процесс прекращен  
SIGCONT Нет Продолжать процесс HELD ; игнорировать сигнал если процесс не HELD Продолжать если HELD  
SIGSTOP* Нет Приостановить процесс HOLD сигнал процесса
SIGTSTP* Нет Игнорировать сигнал Не поддерживается QNX
SIGTTIN Нет -"- -"-
SIGTTOU Нет -"- -"-
                                                       

 

Специфические сигналы QNX

Сигнал Отловить/ игнорировать Действие по умолчанию Описание
SIGBUS** Да Прекратить процесс Обозначает ошибку паритета в памяти (специфическая интерпретация QNX)
SIGDEV Да -"- Генерируется когда значительное и запрошенное событие происходит в Device Manager
SIGPWR Да -"- Запрошена "мягкая" перезагрузка <Ctrl>-<Alt>-<Shift>-<Del> или утилита shutdown
                               

 

Традиционные сигналы UNIX

Сигнал Отловить/ игнорировать Действие по умолчанию Описание
SIGIOT+ Да Прекратить процесс Инструкция IOT
SIGSYS+ Да -"- Неправильный аргумент системного вызова
SIGWINCH+ Да -"- Смена окна
SIGURG+ Да -"- Особая ситуация на сокете
SIGPOLL+ Да -"- Произошло опрашиваемое событие
SIGEMT+ Да -"- инструкция EMT (эмулятор ловушка)
SIGTRAP Да -"- Неподдерживаемое
                                                               

 

* Сервер может защитить себя от подобных сигналов используя функцию С qnx_pflags(). Для этого сервер должен иметь superuser привилегии.

** Если происходит вторая такая же ошибка пока процесс находится в обработчике сигнала ошибки - то процесс будет прекращен.

+ Этот сигнал определен для совместимости с некоторыми ранними системами UNIX; он не генерируется какими либо QNX компонентами.

 

Определение обработки сигналов

Для определения типа обработки для каждого сигала используется функция ANSI C signal() или функция POSIX sigaction().

Функция sigaction() предоставляет больше контроля над средой обработки сигналов.

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

 

Отлов сигналов

Надо учитывать некоторые моменты относительно процессов, которые отлавливают сигналы с помощью функции обработки сигналов.

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

Если процесс не возвращается из обработчика сигналов - то он может использовать следующие функции С: либо siglongjmp() либо longjmp(), но предпочтительнее siglongjmp(). При использовании longjmp() сигнал остается заблокированным.

 

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

Библиотечные функции POSIX и ANSI C безопасны для использования в обработчиках сигналов. Вам не следует пытаться использовать другие библиотечные функции, поскольку результат будет непредсказуемым. По тем же причинам не надо использовать в вашей программе пользовательские функции за исключением случаев когда они re-entrant.

_exit{) access() аlarm() cfgetispeed() cfgetospeed() cfsetispeed() cfsetospeed() chdir() chmod() chown() close() creat() dup2() dup() execle()  execve() fcntl() fork() fstat() getegid() geteuid() getgid() getgroups() getpgrp() getpid() getppid() getuid() kill() link() Iseek() mkdir() mkfifo() open() pathconf()) pause() pipe() read() rename() rmdir() setgid() setpgid() setsid() setuid() sigaction() sigaddset() sigdelset() sigemptyset() sigfillset() sigismember() signal() sigpending() sigprocmask() sigsuspend() sleep() stat() sysconf() tcdrain() tcflow() tcflush() tcgetattr() tcgetpgrp() tscendbreak() tcsetattr() tcsetgrp() time() times() umask() uname() unlink() ustat() utime() wait() waitpid() write()    

 

Блокировка сигналов

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

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

Некоторые системы UNIX имеют испорченную реализацию обработчиков сигналов в том плане, что они перенастраивают сигнал на действие по умолчанию вместо блокировки. Как результат некоторые UNIX приложения вызывают функцию signal() в обработчике сигналов, чтобы настроить его как было. Тут есть два источника ошибок. Во-первых, если в момент, когда ваша программа в обработчике, но еще не вызвала signal(), приходит другой сигнал, то программа может быть убита. Во-вторых, если сигнал приходит сразу же после вызова signal() то вы можете рекурсивно войти в обработчик. QNX поддерживает блокировку сигналов и поэтому свободна от этих проблем. Вам не надо вызывать signal() в вашем обработчике. Если вы покидаете ваш обработчик длинным переходом - то вы должны использовать функцию siglongjmp().

 

3. Сигналы и сообщения.

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

1) процесс разблокируется

2) произойдет обработка сигнала

3) Send() или Receive() вернет ошибку

Если ваш процесс был заблокирован на отправку - это не представляет проблемы, так как получатель еще не получил сообщение. Но если процесс был заблокирован на ответ - то вы не будете знать: было ли обработано посланное сообщение и запускать ли еще раз Send()

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

• нормально завершить первый запрос — отправителю гарантировано, что его сообщение было должным образом обработано

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

Когда сервер отвечает процессу, который был заблокирован на сигнал, сигнал произведет свое действие сразу же по возвращению Send() отправителя.


Лекция №7.


Поделиться:



Последнее изменение этой страницы: 2019-04-21; Просмотров: 201; Нарушение авторского права страницы


lektsia.com 2007 - 2024 год. Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав! (0.091 с.)
Главная | Случайная страница | Обратная связь