Что такое асинхронное сообщение
Перейти к содержимому

Что такое асинхронное сообщение

  • автор:

Асинхронное сообщение

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

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

Пользовательским программам необходимо выполнить два шага, чтобы разрешить асинхронное уведомление от входного файла. Во-первых, они определяют процесс как «владельца» этого файла. Когда процесс вызывается командой F_SETOWN , используя системный вызов fcntl , process ID владельца процесса сохраняется для последующего использования в filp->f_owner . Этот шаг необходим для ядра, чтобы знать, кого уведомлять. Для того, чтобы действительно разрешить асинхронное уведомление, пользовательским программам необходимо установить в устройстве флаг FASYNC с помощью команды F_SETFL fcntl .

После выполнения этих двух вызовов входной файл может запросить доставку сигнала SIGIO при получении новой информации. Этот сигнал передаётся в процесс (или группу процессов, если значение отрицательное), хранящийся в filp->f_owner .

Например, следующие строки кода пользовательской программы разрешают асинхронное уведомление текущего процесса для входного файла stdin :

signal(SIGIO, &input_handler); /* пустышка; лучше использовать sigaction( ) */

fcntl(STDIN_FILENO, F_SETOWN, getpid( ));

oflags = fcntl(STDIN_FILENO, F_GETFL);

fcntl(STDIN_FILENO, F_SETFL, oflags | FASYNC);

Программа в исходниках, названная asynctest , является простой программой, которая, как показано, считывает stdin . Она может быть использована для тестирования асинхронных возможностей scullpipe . Программа похожа на cat , но не прекращается при достижении конца файла; она реагирует только на ввод, но не на отсутствие ввода.

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

Осталась одна проблема с уведомлением ввода. Когда процесс получает SIGIO , он не знает, какой входной файл предлагает новый ввод. Если более чем один файл имеет возможность асинхронно уведомить об этом процесс, ожидающий ввод, приложение должно по-прежнему прибегать к poll или select , чтобы выяснить, что произошло.

С точки зрения драйвера

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

1. При вызове F_SETOWN ничего не происходит, кроме того, что filp->f_owner присваивается значение.

2. Когда выполняется F_SETFL , чтобы включить FASYNC , вызывается метод драйвера fasync . Этот метод вызывается всякий раз, когда в filp->f_flags меняется значение FASYNC для уведомления драйвера об изменении, чтобы он мог реагировать должным образом. При открытии файла флаг по умолчанию очищается. Мы будем рассматривать стандартную реализацию метода драйвера далее в этом разделе.

3. При поступлении данных все процессы, зарегистрированные для асинхронного уведомления, должны отправить сигнал SIGIO .

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

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

Две функции, которые вызывает драйвер, соответствуют следующим прототипам:

int fasync_helper(int fd, struct file *filp, int mode, struct fasync_struct **fa);

void kill_fasync(struct fasync_struct **fa, int sig, int band);

fasync_helper вызывается, чтобы добавить или удалить записи из списка заинтересованных процессов, когда для открытого файла изменяется флаг FASYNC . Все эти аргументы, за исключением последнего, предоставляются методом fasync и могут быть переданы напрямую через него. kill_fasync используется, чтобы при поступлении данных просигнализировать заинтересованным процессам. Её аргументами являются сигнал для отправки (обычно SIGIO ) и диапазон, который почти всегда POLL_IN (* POLL_IN является символом, используемым в коде асинхронного уведомления; это эквивалентно POLLIN | POLLRDNORM.) (но это может быть использовано для передачи «срочно» или о наличии данных во вспомогательном канале в сетевом коде). Вот как реализуется метод fasync в scullpipe :

static int scull_p_fasync(int fd, struct file *filp, int mode)

struct scull_pipe *dev = filp->private_data;

return fasync_helper(fd, filp, mode, &dev->async_queue);

Понятно, что вся работа выполняется fasync_helper . Однако, было бы невозможно реализовать функциональность без метода в драйвере, так как вспомогательной функции требуется доступ к правильному указателю на структуру fasync_struct * (здесь &dev->async_queue ) и только драйвер может предоставить такую информацию.

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

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

Может показаться, что мы всё доделали, но всё ещё отсутствует одна вещь. Мы должны вызвать наш метод fasync , когда файл закрыт для удаления этого файла из списка активных асинхронных читателей. Хотя этот вызов требуется, только если filp->f_flags имеет установленный FASYNC , вызов функции в любом случае не повредит и является обычной реализацией. Следующие строчки, например, являются частью метода release в scullpipe :

/* удалить этот filp из асинхронно уведомляемых filp-ов */

scull_p_fasync(-1, filp, 0);

Структура данных, лежащая в основе асинхронного уведомления, почти идентична структуре wait_queue , потому что обе эти ситуации связаны с ожиданием события. Разница в том, что вместо структуры task_struct используется структура file . Затем, чтобы послать сигнал процессу, для получения f_owner используется структура file из очереди.

Диаграммы взаимодействия: крупным планом

И еще одно — мы легко можем представить ситуацию посылки сообщения в зависимости от истинности некоторого условия. Например, если цена приглянувшейся нам в магазине вещи меньше ста условных единиц, мы вполне можем приобрести ее за наличные. Покупку на сумму от 100 до 1000 долларов можно оплатить кредитной картой, а чтобы купить нечто, стоящее дороже 1000 у. е., придется брать кредит . А как изобразить такие ситуации ( ветвления ) на диаграмме последовательностей? Да легко (рис. 5.5)!

Рис. 5.5.

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

Ранее мы говорили, что сообщение посылается объектом в расчете на определенную реакцию, на то, что за этим последует некоторая деятельность . Например, посылка ответного сообщения. А как на диаграммах последовательностей изображаются ответные сообщения? Обычно их изображают пунктирной линией со стрелкой, хотя часто они имеют точно такой же вид, как и обычные сообщения, только направлены в противоположную сторону. Как именно их рисовать — пунктирной линией или сплошной — решать вам. Это абсолютно не принципиально (рис. 5.6).

Рис. 5.6.

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

Другой вид сообщений — асинхронные сообщения. Они не ждут ответа, не приостанавливают поток выполнения — сразу после их посылки происходит немедленный переход к следующему шагу, и последовательность продолжается. Входя в офис поутру и говоря коллегам «hello, how are you?», вы ведь не ждете, что они остановят вас и начнут в течение часа рассказывать о своих проблемах? Это просто формальное приветствие, не предусматривающее ответа (асинхронное). Асинхронные сообщения изображаются сплошной линией с обычной (составленной из двух отрезков) стрелкой на конце. А как изображаются ответные сообщения, мы уже знаем (рис. 5.7):

Рис. 5.7.

И еще. Возможны случаи, когда нам известен адресат сообщения, но неизвестен его отправитель. С примерами таких сообщений (в бумажном виде) в советские времена довольно часто встречались секретари госучреждений. Такие сообщения называют найденными. Или обратный случай: отправитель известен, а получатель — нет. Пример? Да хотя бы записки, запечатанные в бутылки, которые когда-то бросали в море жертвы кораблекрушений! Такие сообщения называют. Да-да, именно — потерянными. На диаграммах они изображаются без особых изысков (рис. 5.8).

Рис. 5.8.

Рассмотрим, наконец, «полный» пример диаграммы последовательностей. И конечно же, этот пример мы возьмем с сайта шуток на UML http://www.umljokes.com (рис. 5.9).

увеличить изображение
Рис. 5.9.

Не правда ли, очень жизненный анекдот? А вот еще один пример, показывающий, что, задав вопрос «сколько будет два плюс два?», вы не всегда услышите в ответ «четыре». Ответ на любой вопрос всегда сильно зависит от личности, настроения, уровня интеллекта отвечающего, даже от его профессии. И вот вам тому доказательство (рис. 5.10).

Элементы графической нотации диаграммы кооперации

Сообщение (message) — спецификация передачи информации от одного элемента модели к другому с ожиданием выполнения определенных действий со стороны принимающего элемента.

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

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

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

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

Рис. 7.7. Графическое изображение различных типов сообщений на диаграмме кооперации

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

Каждое сообщение может быть помечено строкой текста, которая имеет следующий формат:

Предшествующие сообщения — это разделенные запятыми номера сообщений , записанные перед наклонной чертой: сообщения ‘,’>* . Если список номеров сообщений пуст, то вся запись , включая наклонную черту, опускается. Если номера сообщений указываются, то они должны соответствовать номерам других сообщений на этой же диаграмме кооперации . Смысл указания предшествующих сообщений заключается в том, что данное сообщение не может быть передано, пока не будут переданы своим адресатам все сообщения , номера которых записаны в данном списке.

Выражение последовательности — это разделенный точками список отдельных термов последовательностей, после которого записывается двоеточие: ‘:’

Каждый из термов представляет отдельный уровень процедурной вложенности в форме законченной итерации. Наиболее верхний уровень соответствует самому левому терму последовательности. Если все потоки управления параллельные, то вложенность отсутствует. Каждый терм последовательности имеет следующий синтаксис : [Целое число | Имя] [Рекуррентность] .

  • Целое число указывает на порядковый номер сообщения в процедурной последовательности верхнего уровня. Сообщения , номера которых отличаются на единицу, следуют подряд один за другим.
  • Имя в форме буквы алфавита используется для спецификации параллельных потоков (нитей) управления. Сообщения , которые отличаются только именем, являются параллельными на этом уровне вложенности. На одном уровне вложенности все нити управления эквивалентны в смысле приоритета передачи сообщений .
  • Рекуррентность используется для указания итеративного или условного характера выполнения передачи сообщений . Семантика рекуррентности представляет ноль или больше сообщений , которые должны быть выполнены в зависимости от записанного условия. Возможны два варианта записи рекуррентности:
  • ‘*»[‘Предложение-итерация’]’ для записи итеративного выполнения соответствующего выражения. Итерация представляет последовательность сообщений одного уровня вложенности. Предложение-итерация может быть опущено, если количество итераций никак не специфицируется. Наиболее часто предложение-итерация записывается на псевдокоде или языке программирования. В языке UML формат записи этого предложения строгим образом не определен.
  • ‘[‘Предложение-условие’]’ для записи ветвления. Эта форма записи специфицирует условие для данного сообщения , передача которого по данной ветви возможна только при его истинности.

В общем случае предложение-условие — обычное булевское выражение и предназначено для синхронизации отдельных нитей потока управления. Записывается в квадратных скобках и может быть опущено, если оно отсутствует у данного сообщения . Наличие этого условия обеспечивает передачу сообщения только в том случае, если это условие принимает значение » истина «. Предложение-условие может быть записано на обычном тексте, псевдокоде или некотором языке программирования.

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

Имя сообщения , записанное в сигнатуре после возвращаемого значения, означает имя события , которое инициируется объектом-получателем сообщения после его приема. Наиболее часто таким событием является вызов операции у объекта-получателя. Это может быть реализовано различными способами, один из которых – явное указание в качестве имени сообщения вызываемой операции . Тогда соответствующая операция должна быть определена в том классе, которому принадлежит объект-получатель.

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

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

В языке UML определены следующие стереотипы сообщений :

  • > (вызвать) – сообщение , требующее вызова операции или процедуры объекта-получателя. Если сообщение с этим стереотипом рефлексивное, то оно инициирует локальный вызов операции у пославшего это сообщение объекта .
  • > (возвратить) – сообщение , возвращающее значение выполненной операции или процедуры вызвавшему ее объекту . Значение результата может инициировать ветвление потока управления.
  • > (создать) – сообщение , требующее создания другого объекта для выполнения определенных действий. Созданный объект может стать активным (ему передается поток управления), а может остаться пассивным.
  • > (уничтожить) – сообщение с явным требованием уничтожить соответствующий объект . Посылается в том случае, когда необходимо прекратить нежелательные действия со стороны существующего в системе объекта , либо когда объект больше не нужен и должен освободить задействованные им системные ресурсы.
  • > (послать) – обозначает посылку другому объекту сигнала, который асинхронно инициируется одним объектом и принимается (перехватывается) другим. Отличие сигнала от сообщения заключается в том, что сигнал должен быть явно описан в том классе, объект которого инициирует его передачу.

Рекомендации по построению диаграмм кооперации

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

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

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

Общий форум

Здравствуйте!
Подскажите пожалуйста есть ли в moodle аналог электронной почты. Так называемое асинхронное общение? Та взаимосвязь которая организованна в moodle отправка сообщения диалогом это синхронное общение.
Мы в вузе делаем образовательную среду и вот необходима функция асинхронного общение.
Подскажите пожалуйста есть ли такая возможность?

Сумма оценок: —
В ответ на Иван Маркизов

Re: Асинхронное общение

от Vadim Tabunshchik — понедельник, 15 января 2018, 18:06

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

Если нужна переписка по Email прямо в Мудл, смотрите доп. плагины, например: jmail, Quickmail, Nice Email, QuickmailSMS, etc

Сумма оценок: —
Постоянная ссылка Показать сообщение-родителя Ответить
В ответ на Иван Маркизов

Re: Асинхронное общение

от Victor Sundukov — понедельник, 15 января 2018, 19:08

Мне кажется, что элемент курса «форум» как раз и предназначен для асинхронного общения. Преподаватель или студенты задают в форуме свои вопросы, другие студенты или преподаватель — отвечают. Форма общения определяется настройкой, там же и подключается дублирование на почту! Сама система MOODLE является асинхронной, если к ней не «прикручено» что-нибудь синхронного, типа видеоконференции или чата.

Сумма оценок: —
Постоянная ссылка Показать сообщение-родителя Ответить
В ответ на Victor Sundukov

Re: Асинхронное общение

от Alexey Piguzov — понедельник, 15 января 2018, 19:25

Абсолютно согласен, мало того имел честь общаться с экспертов при аккредитации, Форум это асинхронное общение. Чат синхронное. Именно это и имеется в виду во ФГОСах.

Сумма оценок: —
Постоянная ссылка Показать сообщение-родителя Ответить

  • ◄ Обновление с 3.0.1 до 3.4.
  • Смена адреса портала ►

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *