Что аналогия C к Структуре События LabVIEW?

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

Как опытный программист LabVIEW с достойным пониманием C, мне любопытно, как можно было бы пойти об эмуляции структуры события LabVIEW в C; предпочтительно в соответствии с Linux. Маленький пример кода (как тот в ссылке выше) иллюстрирующий, как это могло бы быть сделано, будет очень цениться. Кроме того, если бы там уже существует сторонние библиотеки (для Linux) для добавления этой платформы события к C, который был бы хорош знать также.Спасибо.

5
задан SiegeX 11 March 2010 в 02:32
поделиться

4 ответа

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

Уловка сводится к тому, как не допустить, чтобы этот основной цикл дико вращал ЦП. Один простой трюк - заставить основной цикл спать в течение определенного периода времени, а затем проверить, нужно ли обрабатывать какие-либо события, а затем снова засыпать. У этого есть обратная сторона - появление задержки.Лучше всего, если это применимо, чтобы операционная система выполняла эти проверки как часть своих обычных операций, а затем разбудила основной цикл вашего приложения, когда произошло что-то интересное. В Linux это делается с помощью системного вызова select, но select имеет ограничение, заключающееся в том, что он может указывать только ресурс, который может быть связан с файловым дескриптором, поэтому устройства, стандартный ввод, файлы, сетевые порты в порядке.

Edit: Чтобы прояснить для моих противников: я не отрицаю существование аппаратных прерываний. Да, в случаях, когда код имеет прямой доступ к аппаратным прерываниям для всех событий, которые он хочет обрабатывать (например, встроенная система или драйвер устройства), вы можете написать действительно управляемый событиями код с несколькими точками входа, который не занят ожиданием или засыпанием . Однако в обычной программе C уровня приложения, работающей под Linux, эта архитектура кода буквально не существует, а эмулируется на уровне приложения. Любое приложение Linux будет иметь основной цикл и хотя бы один поток выполнения. Этот поток может быть приостановлен планировщиком, но он всегда существует и всегда имеет указатель инструкции на конкретную инструкцию. Если код покидает main (), программа завершается. Код не может вернуться из main и получить обратный вызов позже от ядра. Код имеет единственную точку входа и должен вызывать свои различные обработчики событий вручную.За исключением драйвера устройства (или очень специфического системного кода, использующего сигналы), вы не можете заставить ядро ​​или оборудование автоматически вызывать определенную функцию, если пользователь щелкнул определенный пункт меню, вместо этого ваш код работает, сам обнаруживает это событие, и вызывает правильный обработчик событий.

Вы можете сказать LabView «Вызовите эту функцию, когда произойдет XX». В языке C вы указываете своему собственному коду отправки события «Вызовите эту функцию, когда произойдет XX».

Я пытаюсь сказать (плохо?), Что архитектура структуры событий не является родной для приложения C / Linux. Он должен быть эмулирован вашим кодом за счет наличия основного потока отправки, который создает видимость управляемой событиями среды. Либо вы делаете это вручную, либо используете библиотеку событий, которая делает это за кулисами, чтобы создать видимость модели, управляемой событиями. LabView использует второй подход, поэтому кажется, что код не запускается, когда не происходит никаких событий, но на самом деле существует собственный код C ++ LabView, который управляет очередями событий. Это не означает, что он все время занят ожиданием, как я сказал ранее, существуют системные вызовы, такие как select и sleep, которые код может использовать для определения времени процессора, когда у него нет работы, но код не может просто прекратить выполнение.

Допустим, вы хотите написать программу, управляемую событиями, с двумя обработчиками событий. Один, который вызывается каждые десять секунд, называется tick (), другой, который вызывается каждый раз при нажатии клавиши, называется key (), а тот, который вызывается каждый раз, когда набирается слово «foobar», называется foobar (). Вы можете определить эти три обработчика событий, но, кроме того, вам понадобится некий главный поток диспетчеризации, который в основном выполняет

 while not quitting
   If 10 seconds have elapsed, call tick()
   If Key has been Pressed
       call key() 
       add save the key to our key buffer
       If buffer now contains "foobar" call foobar() and clear buffer
   Wait()

. Если все события, о которых вы заботитесь, являются событиями системного уровня или событиями временного уровня, вы можете Wait () может просто сообщить ядро «разбуди меня, когда произойдет одно из этих событий», так что мне не нужно «занятое ожидание». Но вы не можете просто сказать ядру «вызвать foobar (), когда« foobar нажат ». У вас должно быть приложение код диспетчеризации уровня, который имитирует структуру событий. Ваша программа на C имеет только одну точку входа из ядра для каждого потока выполнения. Если вы посмотрите на библиотеки, которые предоставляют модели диспетчеризации событий, такие как Qt, вы обнаружите, что они работает вот так под капотом.

7
ответ дан 13 December 2019 в 19:25
поделиться

Мне нравится libev за такие вещи.

2
ответ дан 13 December 2019 в 19:25
поделиться

Большинство наборов инструментов GUI ( GTK , Qt и т. Д.) Реализуют собственную абстракцию цикла событий. Я вставил пример программы сюда , потому что включать ее в ответ было довольно долго. Это перенос упомянутого вами примера LabVIEW на язык C с использованием инструментария GTK, потому что я знаком с ним. Однако основы цикла обработки событий не сильно отличаются от других наборов инструментов.

2
ответ дан 13 December 2019 в 19:25
поделиться

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

Если вы хотите вводить данные с помощью мыши, вам нужно более конкретно указать свою платформу, поскольку C / C ++ не имеет встроенной поддержки мыши или окон.

0
ответ дан 13 December 2019 в 19:25
поделиться
Другие вопросы по тегам:

Похожие вопросы: