Jump to content

Цикл событий

(Перенаправлено из основного цикла )

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

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

Цикл событий может использоваться в сочетании с реактором , если поставщик событий следует файловому интерфейсу , который можно выбрать или «опросить» (системный вызов Unix, а не фактический опрос ). Цикл событий почти всегда работает асинхронно с отправителем сообщения.

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

Передача сообщений [ править ]

программы Говорят, что насосы сообщений «перекачивают» сообщения из очереди сообщений (назначенной и обычно принадлежащей базовой операционной системе) в программу для обработки. В самом строгом смысле цикл событий — это один из методов реализации межпроцессного взаимодействия . Фактически обработка сообщений существует во многих системах, включая уровня ядра компонент операционной системы Mach . Цикл событий — это особый метод реализации систем, использующих передачу сообщений .

Альтернативные конструкции [ править ]

Этот подход отличается от ряда других альтернатив:

  • Традиционно программа просто запускалась один раз, а затем закрывалась. Этот тип программ был очень распространен на заре компьютерной эры и не имел какой-либо формы взаимодействия с пользователем. Это до сих пор часто используется, особенно в виде программ, управляемых из командной строки . Любые параметры настраиваются заранее и передаются за один раз при запуске программы.
  • Дизайн на основе меню. Они по-прежнему могут включать в себя основной цикл, но обычно не считаются управляемыми событиями в обычном смысле. [ нужна ссылка ] Вместо этого пользователю предоставляется постоянно сужающийся набор опций до тех пор, пока задача, которую он хочет выполнить, не станет единственным доступным вариантом. Доступна ограниченная интерактивность через меню.

Использование [ править ]

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

функция  основная    инициализировать()     пока  сообщение != выйти        сообщение:= get_next_message()        процесс_сообщение (сообщение)     конец   , пока  завершения   функция 

Файловый интерфейс [ править ]

В Unix парадигма « все есть файл » естественным образом приводит к циклу событий на основе файла. Чтение и запись в файлы, межпроцессное взаимодействие, сетевое взаимодействие и управление устройством выполняются с помощью файлового ввода-вывода, при этом цель идентифицируется файловым дескриптором . Системные вызовы select и poll позволяют отслеживать набор файловых дескрипторов на предмет изменения состояния, например, когда данные становятся доступными для чтения.

Например, рассмотрим программу, которая читает постоянно обновляемый файл и отображает его содержимое в системе X Window , которая взаимодействует с клиентами через сокет (либо домен Unix , либо Berkeley ):

def   main  ():      file_fd   =   open  (  "logfile.log"  )      x_fd   =   open_display  ()      struct_interface  ()      while   True  :          rlist  ,   _  ,   _   =   select  .  select  ([  file_fd  ,   x_fd  ],   [],   []):          если   file_fd   в   rlist  :              data   =   file_fd  .  read  ()              append_to_display  (  data  )              send_repaint_message  ()          if   x_fd   в   rlist  :              process_x_messages  () 

Обработка сигналов [ править ]

Одна из немногих вещей в Unix, которая не соответствует файловому интерфейсу, — это асинхронные события ( сигналы ). Сигналы принимаются в обработчиках сигналов — небольших ограниченных фрагментах кода, которые выполняются, пока остальная часть задачи приостановлена; если сигнал получен и обработан во время блокировки задачи select(), select вернется раньше с EINTR ; Если сигнал получен, когда задача привязана к ЦП , задача будет приостановлена ​​между инструкциями до тех пор, пока обработчик сигнала не вернется.

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

Решение, полученное с помощью POSIX, - это pselect() вызов, который похож на select() но требует доп. sigmask параметр, описывающий маску сигнала . Это позволяет приложению маскировать сигналы в основной задаче, а затем снимать маску на время выполнения задачи. select() вызов таким образом, чтобы обработчики сигналов вызывались только тогда, когда приложение привязано к вводу-выводу . Однако реализации pselect() не всегда были надежными; версии Linux до 2.6.16 не имеют pselect() системный вызов, [1] заставить glibc эмулировать его с помощью метода, склонного к тому же состоянию гонки pselect() призвано избежать.

Альтернативное, более портативное решение — преобразовать асинхронные события в события на основе файлов с помощью трюка self-pipe , [2] где «обработчик сигнала записывает байт в канал, другой конец которого контролируется select() в основной программе». [3] В ядре Linux версии 2.6.22 появился новый системный вызов signalfd() добавлена ​​возможность приема сигналов через специальный файловый дескриптор.

Реализации [ править ]

HTML/Javascript [ править ]

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

Приложения для Windows [ править ]

В операционной системе Microsoft Windows процесс, который взаимодействует с пользователем, должен принимать входящие сообщения и реагировать на них, что почти неизбежно происходит с помощью цикла обработки сообщений в этом процессе. В Windows сообщение приравнивается к событию, созданному и наложенному на операционную систему. Событием может быть взаимодействие пользователя, сетевой трафик, системная обработка, активность таймера, межпроцессное взаимодействие и другие. Для неинтерактивных событий, предназначенных только для ввода-вывода, в Windows предусмотрены порты завершения ввода-вывода . Циклы портов завершения ввода-вывода выполняются отдельно от цикла сообщений и не взаимодействуют с циклом сообщений «из коробки».

«Сердцем» большинства Win32 приложений является функция WinMain() вызывает GetMessage() , которая в цикле . GetMessage() блокируется до тех пор, пока не будет получено сообщение или «событие» (с функцией PeekMessage() в качестве неблокирующей альтернативы). После некоторой дополнительной обработки он вызывает DispatchMessage() , который отправляет сообщение соответствующему обработчику, также известному как WindowProc . Обычно сообщения, у которых нет специального WindowProc(), отправляются в DefWindowProc , который используется по умолчанию. DispatchMessage() вызывает WindowProc дескриптора HWND ( сообщения зарегистрированного с помощью функции RegisterClass() ).

Порядок сообщений [ править ]

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

Однако для некоторых сообщений действуют другие правила, например сообщения, которые всегда принимаются последними, или сообщения с другим документированным приоритетом. [4]

X Window System [ править ]

Цикл событий Xlib [ править ]

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

Очень немногие программы используют Xlib напрямую. В более распространенном случае наборы инструментов GUI, основанные на Xlib, обычно поддерживают добавление событий. Например, наборы инструментов, основанные на Xt Intrinsics, имеют XtAppAddInput() и XtAppAddTimeout().

Обратите внимание, что вызывать функции Xlib из обработчика сигналов небезопасно, поскольку приложение X могло быть прервано в произвольном состоянии, например, в XNextEvent. См. [1] решение для X11R5, X11R6 и Xt.

Цикл событий GLib [ править ]

Цикл событий GLib изначально был создан для использования в GTK , но теперь используется и в приложениях без графического интерфейса, таких как D-Bus . Опрашиваемый ресурс представляет собой набор дескрипторов файлов, которые интересуют приложение; блок опроса будет прерван, если поступит сигнал или истечет таймаут (например, если приложение указало таймаут или задачу ожидания). Хотя GLib имеет встроенную поддержку файловых дескрипторов и дочерних событий завершения, можно добавить источник событий для любого события, которое может быть обработано в модели подготовки-проверки-отправки. [2]

Библиотеки приложений, построенные на цикле событий GLib, включают GStreamer и асинхронного ввода-вывода методы GnomeVFS , но GTK остается наиболее заметной клиентской библиотекой. События из оконной системы X X — считывание из сокета ) преобразуются GDK в события GTK и отправляются в виде сигналов GLib на объекты виджетов приложения.

Циклы выполнения macOS Core Foundation [ править ]

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

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

См. также [ править ]

Ссылки [ править ]

  1. ^ «Linux_2_6_16 — новички в ядре Linux» . kernelnewbies.org . Проверено 03 марта 2021 г.
  2. ^ Диджей Бернштейн. «Трюк с самодельной трубкой» .
  3. ^ ОШИБКИ, pselect(2): синхронное мультиплексирование ввода-вывода – Linux программиста Руководство – Системные вызовы
  4. ^ Функция GetMessage() со списком приоритетов сообщений.

Внешние ссылки [ править ]

Arc.Ask3.Ru: конец переведенного документа.
Arc.Ask3.Ru
Номер скриншота №: fbab8f17ef03d737bbf8a10716e9d199__1716460080
URL1:https://arc.ask3.ru/arc/aa/fb/99/fbab8f17ef03d737bbf8a10716e9d199.html
Заголовок, (Title) документа по адресу, URL1:
Event loop - Wikipedia
Данный printscreen веб страницы (снимок веб страницы, скриншот веб страницы), визуально-программная копия документа расположенного по адресу URL1 и сохраненная в файл, имеет: квалифицированную, усовершенствованную (подтверждены: метки времени, валидность сертификата), открепленную ЭЦП (приложена к данному файлу), что может быть использовано для подтверждения содержания и факта существования документа в этот момент времени. Права на данный скриншот принадлежат администрации Ask3.ru, использование в качестве доказательства только с письменного разрешения правообладателя скриншота. Администрация Ask3.ru не несет ответственности за информацию размещенную на данном скриншоте. Права на прочие зарегистрированные элементы любого права, изображенные на снимках принадлежат их владельцам. Качество перевода предоставляется как есть. Любые претензии, иски не могут быть предъявлены. Если вы не согласны с любым пунктом перечисленным выше, вы не можете использовать данный сайт и информация размещенную на нем (сайте/странице), немедленно покиньте данный сайт. В случае нарушения любого пункта перечисленного выше, штраф 55! (Пятьдесят пять факториал, Денежную единицу (имеющую самостоятельную стоимость) можете выбрать самостоятельно, выплаичвается товарами в течение 7 дней с момента нарушения.)