用于读出传感器数据的线程或计时器
Thread or timer to read sensor data out?
我的 Linux C++应用程序会定期读取传感器数据。读出是通过简单的文件 I/O 操作完成的(操作系统正在写入文件,应用程序正在从该文件读取)。关于我的平台的一些信息:
- 我有超线程的单核处理器
- 传感器数据更新频率为 1 秒
- 应用程序 GUI 在主线程中运行,不应被阻止
我考虑了两种读取传感器数据的方法:
- 在主应用程序线程中运行的计时器
- 具有无限循环的独立线程,可读取传感器数据,然后休眠
哪种方法更有意义,还有其他选择吗?这两种解决方案的成本是多少(例如,第一种方法阻塞主线程或第二种方法中的上下文切换)?
我对你的应用程序或硬件一无所知,但这里有一些事情需要考虑:
- 如果使用线程,则必须创建某种通信通道来告诉主线程数据已更新。通常这是一个pipe(),因为信号本质上是不可靠的,条件锁不适用于I/O多路复用(即select()/poll())。
- 你能在不阻塞的情况下获得整个数据集吗?如果是这样,那么只需在主线程中阅读它可能更容易。但是,如果你的读取可以阻塞,你可能需要更多"跟踪我的读取状态以将其合并到我的中央 select()",而线程可以阻塞,直到有更多数据可用。
因此,这两种解决方案都不会自动"更容易"做到。
对于每秒只发生一次的读取,我不会担心"上下文切换";这无关紧要。
主线程还需要做什么?如果它阻止可以吗?如果是这样,那么您不需要在单独的线程中执行计时器等。
如果主线程无法阻塞等待定期计时器,则必须创建一个单独的线程。线程之间的数据通信可以通过两个线程都可以访问的对象进行,并通过互斥锁(查找pthread_mutex_t)进行保护,这非常简单。
至于哪种解决方案会更好,成本是多少,这取决于主线程在做什么。但是对于这么简单的事情,无论哪种方式都应该大致相同,并且上下文切换应该不会影响任何事情。对性能影响最大的是读取的性能密集程度。
即使对于没有超线程的单核 CPU,每秒切换一次上下文的成本也不是问题,特别是考虑到应用程序在用户空间中运行,因此并不是真正的时间关键。在主线程中轮询传感器会使应用程序的逻辑复杂化。因此,我建议您为此目的启动一个线程。
睡眠循环会扭曲计时,因为每次迭代的时间将超过 1 秒。 计时器没有这个问题,它们是为这种情况而设计的。所以选择一个计时器。
在性能方面没有区别,因为您每秒只触发一次。
如果 Linux 驱动程序每秒读取传感器数据并将其写入设备文件,则不应在应用程序中复制计时器逻辑。在 1 秒睡眠后,应用程序可能仍会读取与 1 秒前相同的数据。更好的方法是让一个线程调用对设备文件的阻塞读取。当新的传感器数据可用时,阻止读取返回,线程可以处理数据并再次调用读取。
- 并行块(线程清理器)之外的 OpenMP 中的争用条件;误报?
- 计时器是否从另一个线程启动?
- 线程清理器检测到数据争用,问题出在哪里?
- 处理 std::线程包装器类的立即销毁
- 通过shared_ptr同步:线程清理器误报
- 将参数传递给 std::线程包装器
- 多线程包装器
- 简单的线程计时器,请检查是否正常
- QML中的线程渲染器
- 线程包装器实现问题
- 控制台C++中的多线程定时器和I/O
- 在多线程环境中使用 std::string 时 Clang 的线程清理器警告
- 提升thread_group线程限制器
- 线程清理器的抑制文件不起作用:出了什么问题
- 多线程编写器:使用 cpp 的并发问题
- C++串行线程执行器
- 多线程定时器类
- 线程清理器报告使用嵌入式参考计数器时"data race on operator delete(void*)"
- 用类对象提升线程工作器
- 使用 gcc 的线程清理器在启动时会产生各种错误