C与LabVIEW的事件结构类比是什么?

Sie*_*geX 5 c events labview

我在LabVIEW中使用的一个编程结构是事件结构.这使我不必通过轮询不必要地浪费CPU周期,而只在生成我感兴趣的事件时执行操作.

作为一名经验丰富的LabVIEW程序员,对C的理解很好,我很好奇如何用C语言模拟LabVIEW的事件结构; 最好是在Linux下.我们非常感谢一个小代码示例(如上面链接中的示例),说明了如何完成此操作.此外,如果已经存在第三方库(用于Linux)将此事件框架添加到C,那么也很高兴知道.谢谢.

bdk*_*bdk 7

事件结构实际上只是一个隐藏执行线程的抽象.必须在计算机上某处运行一些代码来检查这些事件,然后调用事件处理程序.在C中,您需要自己提供此代码(程序的"主循环").此代码将检查您感兴趣的各种事件源并调用事件处理函数.

然后诀窍就变成了如何不让这个主循环疯狂地旋转CPU.一个简单的技巧是让主循环休眠一段时间,然后检查是否需要处理任何事件,然后再次睡眠.这有引入延迟的缺点.如果适用,更好的技巧是让操作系统在正常操作中执行这些检查,然后在发生有趣事件时唤醒应用程序的主循环.在Linux中,这是通过'select'系统调用来完成的,但是select有一个限制,它只能指定一个可以与文件描述符相关联的资源,因此设备,标准输入,文件,网络端口都可以.

编辑:澄清我的downvoters:我不否认硬件中断的存在.是的,如果代码可以直接访问它希望处理的所有事件的硬件中断(例如嵌入式系统或设备驱动程序),您可以编写真正的"事件驱动"代码,其中包含多个不忙等待或睡眠的入口点.但是,在Linux下运行的普通应用程序级C程序中,此代码体系结构实际上并不存在,而是在应用程序级别进行模拟.任何Linux应用程序都将有一个主循环,至少有一个执行线程.该线程可能会被调度程序暂停,但它始终存在并且始终在特定指令处具有指令指针.如果代码离开main(),则程序结束.代码无法从main返回,并且稍后从内核获得回调.代码有一个入口点,必须手动调用其各种事件处理程序.除了设备驱动程序(或使用信号的非常特定的系统代码)之外,如果用户单击某个菜单项而不是代码正在运行,则无法让内核或硬件自动调用某个函数,检测此事件本身,并调用正确的事件处理程序.

您可以告诉LabView"当XX发生时调用此函数".在C中,您可以告诉自己的事件调度代码"XX发生时调用此函数".

我想说的(糟糕的是?)是事件框架体系结构不是C/Linux应用程序的原生体.它必须由您的代码模拟,具有一个主分派线程,它给出了事件驱动框架的外观.您可以手动执行此操作,也可以使用在幕后执行此操作的事件库来提供事件驱动模型的外观.LabView采用第二种方法,因此在没有事件发生时似乎没有代码在运行,但实际上有LabView自己的C++代码运行来管理事件队列.这并不意味着它一直在忙着等待,正如我之前所说的那样,系统调用如select和sleep代码可以用来在没有工作时产生cpu时间,但代码不能简单停止执行.

假设你想用两个事件处理程序编写一个"事件驱动"程序.每隔十秒调用一次调用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()
Run Code Online (Sandbox Code Playgroud)

如果您关心的所有事件都是系统级事件或时间级别事件,那么Wait()可以简单地告诉内核"当其中一个事情发生时叫醒我"所以我不需要"忙等待" ,但你不能简单告诉内核"按下foobar时调用foobar()".你必须有模拟事件结构的应用程序级调度代码.你的C程序只有一个来自内核的入口点对于每个执行线程.如果你看一下提供事件调度模型的库,比如Qt,你会发现它们的工作原理是这样的.