在尝试实现串行IO的一个相当简单的例程时,我遇到了一个心理障碍。
情况是,我们有一个嵌入式linux板(想想Pi/Beagle),它使用标准的linux termios代码与UART上的另一个设备通信。
问题是我们有两个冲突的需求:
在传输方向上,我们希望阻塞Linux消息队列msgrcv()函数,直到有消息到达供我们发送。
在接收方向上,我们需要等待/阻止传入消息(对于规范模式操作,该消息可以具有终止字符)。
Tx和Rx是异步的,彼此不相关——任何一个都可能希望在任何时候发生。
轮询将是一件痛苦的事情,因为它会导致CPU周期的开销和响应的延迟。
一种方法是将其拆分为两个线程,一个处理Tx并在msgrcv()上进行阻塞,另一个在规范模式下处理Rx并在UART read()上执行阻塞,但这会带来在Tx&Rx过程,并且两者都必须重复地打开&关闭串行端口,Rx线程可能最终不得不轮询信号量,以防Tx想要控制,从而使我们重新进行轮询。
我要强调的是,我对所有这些Linux东西都比较陌生,所以我已经完全准备好向大家展示我在这里缺少的显而易见的解决方案/方法/调用/操作。
是否有某种方法可以阻止UART Rx,但仍能按需传输?
最后,我听从了马丁·詹姆斯的建议,做了这样的事情:
fd = open(serial_port);
pthread_create(TxThread, fd);
pthread_create(RxThread, fd);
Linux似乎对此完全满意,两个线程都能毫无问题地完成它们的工作。
将msgqueue的线程与管道结合使用可能会更简单,因此您可以使用select()/poll()/在管道和串行端口上等待。。。在您的串行tx/rx线程中。
幸运的是,你甚至不必这么做。事实证明,在Linux上(但不是在所有其他unix上!)消息队列ID也是文件描述符,因此您可以在一个poll()调用中等待消息队列和串行端口。你只需要检查哪一个是活动的,就可以知道你必须做什么。
另请参阅为什么消息队列没有类似轮询/选择的机制。