C/C++ - 寻找Linux下的实时定时事件

5
我正在寻找在Linux下使用C/C++进行定时事件的方法。
例如,每100毫秒执行一段代码。(严格实时,不多不少)
目前我看到的唯一选择是:
  • 无限循环,并在每次检查时判断是否到了执行时间。
  • 线程睡眠,直到运行时间到来。
无限检查是否到了运行时间的缺点是它会(过度)占用CPU。
睡眠直到时间到来的缺点是它不精确。睡眠时间只是一个指导,它可能会睡得更久。
现在我想知道你们中是否有人知道如何在Linux下使用C/C++进行实时定时事件。

1
你需要多实时?Linux并不是真正的实时操作系统。 - Carl Norum
是的,这是一个RTOS作业。请看一下QP框架。 - Mihai8
sleep是足够精确的,如果你知道如何使用它。 - Zaffy
你看到了 https://dev59.com/7W015IYBdhLWcg3w7wTF 吗? - jxh
1
这里有一个方法可以提供微秒级精度(不保证但可靠)https://dev59.com/Bm7Xa4cB1Zd3GeqPr54V#14944464 - amdn
5个回答

5
几乎不管你使用什么——select()epoll()usleep()settimer()等方法,有些方法可以采用更高分辨率的超时,有些则不能。但是Linux不是实时操作系统,也不应该期望它在精确定时唤醒您的进程。现在,即使您旋转CPU,内核也可以轻松地挂起您的进程,如果它决定将CPU分配给其他进程或中断处理程序,就可以这样做。
从API角度来看(以及最近的趋势),您应该使用timerfd()——您可以告诉它要使用哪个时钟,并且它可以很好地集成到Linux事件调度机制(epoll、AIO等)中。
除此之外,作为程序员,这超出了您的控制范围。通常需要付出巨大的努力才能从Linux获得接近实时的行为。这涵盖了构建自定义修补过的内核和配置包括中断屏蔽在内的整个世界的亲和力,以及修补您的BIOS并调整硬件。

假设您在一台不高负载的普通x86_64服务器上运行新鲜的vanilla内核,预计唤醒时间约为50微秒(您可以轻松进行基准测试以了解系统的大致情况)。


3
在非实时操作系统上运行,没有用户空间方法是完全可靠的。你说得对,睡眠是不精确的,你可能会睡过头,但同样适用于循环:操作系统可能无法及时调度你的任务,你将错过时间段。
根据你需要的可靠性程度,考虑使用实时操作系统(RTOS),如 QNXRTLinux。RTLinux 的维基有点过时,所以我不确定它的活跃程度。
另一种方法是依赖某些硬件设备的定时(例如 GPS 卡)。你的程序将对外部事件做出反应,而不是尝试计时自己。例如,硬件设备可以公开一个“文件”。你的程序将打开它并阻塞在 read() 上。每 100 毫秒,硬件设备向你发送一些数据。

1
您可以尝试使用RTAI,这是Linux的实时应用程序接口。它允许您为您喜欢的操作系统编写具有严格时间约束的应用程序。与Linux本身一样,这个软件是一个社区努力的产物。
从初学者指南中了解到:
RTAI提供了Linux内核核心的相同服务,并添加了一个工业实时操作系统的特性。它基本上由一个中断调度程序组成:RTAI主要捕获外围设备的中断,并在必要时将它们重新路由到Linux。它不是内核的侵入性修改;它使用HAL(硬件抽象层)的概念来获取来自Linux的信息并捕获一些基本函数。这个HAL为Linux内核提供了很少的依赖关系。这导致了Linux内核的简单适应,易于从一个版本的Linux移植到另一个版本,以及更容易地使用其他操作系统代替RTAI。RTAI认为Linux是一个后台任务,在没有实时活动发生时运行。

0

你也可以考虑使用Linux特定的timerfd_create(2) -以及相关函数-(使用poll(2)进行多路复用/等待,或者使用一些事件库如libevlibevent,或者Gtk或Qt事件循环,这些都会在内部调用poll),或者使用Posix timer_create(2)。另请参阅clock_gettime(2)和相关函数。

我强烈建议阅读time(7)的手册。它解释了很多内容。正如Vlad 所回答的那样,Linux并不是真正的实时内核(即使它可能接近)。


-1

看看libevent:http://libevent.org/

libevent API提供了一种机制,当文件描述符上发生特定事件或超时到达后执行回调函数。此外,libevent还支持由信号或定期超时引起的回调。


内核调用优于第三方库。 - n1nj4

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接