简体   繁体   English

Linux串行IO - 在两个线程之间拆分Tx和Rx?

[英]Linux Serial IO - splitting Tx and Rx between two threads?

I'm having one of those mental-block moments in trying to implement what should be a fairly simple routine, for serial IO. 对于串行IO,我正试图实现应该是一个相当简单的例程。

The situation is that we have an embedded linux board (think Pi / Beagle) which communicates with another device on the UART using the standard Linux termios code . 情况是我们有一个嵌入式linux板(想想Pi / Beagle),它使用标准的Linux termios代码与UART上的另一个设备通信。

The problem is we have two clashing requirements: 问题是我们有两个冲突要求:

In the transmit direction, we want to block on the Linux messaging queue msgrcv() function until a message arrives for us to send. 在传输方向上,我们希望阻止Linux消息传递队列 msgrcv()函数,直到消息到达我们发送。

In the receive direction, we need to wait/block for an incoming message (which can have a termination character for canonical mode operation). 在接收方向,我们需要等待/阻止传入消息(可以具有规范模式操作的终止字符)。

Tx and Rx are asynchronous and not related to each other - either could want to happen at any time. Tx和Rx是异步的,彼此之间没有关系 - 要么想要随时发生。

Polling would be a pain as it introduces an overhead in CPU cycles and delay in response. 轮询会带来痛苦,因为它会引入CPU周期开销和响应延迟。

One approach would be to split this into two threads, one handling the Tx and blocking on msgrcv(), and the other on the Rx and blocking on UART read() in canonical mode - but that would introduce the pain of setting up semaphores between the Tx & Rx processes and both having to repeatedly open & close the serial port, and the Rx thread would presumably end up having to poll the semaphore in case the Tx wanted control, putting us back to polling. 一种方法是将其拆分为两个线程,一个处理Tx并阻塞msgrcv(),另一个处理Rx并在规范模式下阻塞UART read() - 但这会引入设置信号量之间的信号的痛苦Tx和Rx进程都必须重复打开和关闭串口,而Rx线程可能最终不得不轮询信号量,以防Tx需要控制,让我们回到轮询。

I would stress that I'm relatively new to all this Linux stuff, so am entirely ready to be shown the bleeding obvious solution/method/call/operation that I'm missing here. 我要强调的是,我对所有这些Linux的东西都比较新,所以我已经完全准备好显示我在这里缺少的明显的解决方案/方法/调用/操作。

Is there some way to be blocking on the UART Rx but still able to transmit on demand? 是否有某种方法可以阻止UART Rx,但仍能按需传输?

In the end I followed Martin James' suggestion, doing something like this: 最后,我遵循了Martin James的建议,做了这样的事情:

fd = open(serial_port);
pthread_create(TxThread, fd);
pthread_create(RxThread, fd);

Linux seems entirely happy with this, both threads do their jobs with no problem. Linux似乎对此非常满意,两个线程都可以毫无问题地完成工作。

It might be simpler to have a thread for the msgqueue, in combination with a pipe, so you can wait on the pipe and the serial port using select()/poll()/... in your serial tx/rx thread. 为msgqueue创建一个线程可能更简单,与管道结合使用,因此您可以在串行tx / rx线程中使用select()/ poll()/ ...等待管道和串行端口。

Fortunately you don't even have to do that. 幸运的是,你甚至不必那样做。 It turns out that on Linux (but not on all other unixes!) message queue IDs are also file descriptors, so you can just wait on the message queue and the serial port in one poll() call. 事实证明,在Linux上(但不是在所有其他unix上!)消息队列ID也是文件描述符,因此您可以在一个poll()调用中等待消息队列和串行端口。 You only have to check which one is active to figure out what you have to do. 您只需检查哪一个处于活动状态即可确定您必须执行的操作。

See also Why is there no poll/select-like mechanism for message queues . 另请参见为什么消息队列没有轮询/类似选择的机制

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM