【问题标题】:Linux Serial IO - splitting Tx and Rx between two threads?Linux Serial IO - 在两个线程之间拆分 Tx 和 Rx?
【发布时间】:2014-01-02 14:24:15
【问题描述】:

在尝试实现串行 IO 的一个相当简单的例程时,我遇到了一些心理障碍。

情况是我们有一个嵌入式 linux 板(想想 Pi / Beagle),它使用 standard Linux termios code 与 UART 上的另一个设备通信。

问题是我们有两个相互冲突的要求:

在传输方向上,我们希望阻止Linux messaging queue msgrcv() 函数,直到有消息到达供我们发送。

在接收方向,我们需要等待/阻止传入消息(它可以具有规范模式操作的终止字符)。

Tx 和 Rx 是异步的,并且彼此不相关 - 两者都可能随时发生。

轮询会很痛苦,因为它会引入 CPU 周期开销和响应延迟。

一种方法是将其拆分为两个线程,一个处理 Tx 并在 msgrcv() 上阻塞,另一个在 Rx 上并在规范模式下阻塞 UART read() - 但这会带来设置的痛苦在 Tx 和 Rx 进程之间增加信号量,并且都必须重复打开和关闭串行端口,并且 Rx 线程可能最终不得不轮询信号量以防 Tx 想要控制,让我们回到轮询。

我要强调的是,我对所有这些 Linux 东西都比较陌生,所以我完全准备好看到我在这里缺少的明显的解决方案/方法/调用/操作。

是否有某种方法可以阻止 UART Rx,但仍能够按需传输?

【问题讨论】:

  • '但这会带来在 Tx 和 Rx 进程之间设置信号量的痛苦,并且都必须重复打开和关闭串行端口' - 为什么有必要这样做?保持端口开放!
  • 是否不能使用只读标志 (O_RDONLY) 打开 /dev/ttyx 设备文件一次,然后在另一个线程中使用只写标志 (O_WRONLY) 打开?通常你可以打开文件两次......在第一个线程中读取,在另一个线程中写入,而不打开和关闭文件描述符。
  • 文件是否需要打开两次? RX 线程尝试打开端口,如果/成功,则将句柄/fd 作为 tx 线程创建参数传递。此后,rx 线程读取,tx 线程写入。 OP 似乎使本应非常简单的任务过于复杂。
  • 只是一个建议:如果您可以从 sysV 消息队列切换到 POSIX 消息队列,那么(在 linux 上)mqid 是一个文件描述符。您不必阻止或投票。您可以使用select,甚至在收到新消息时让mq_notify 启动一个新线程。
  • @MartinJames - OP 不够熟悉,无法知道“显而易见”是可能的,因为我说我是 Linux 新手,所以不熟悉所有内部工作。

标签: c linux io embedded polling


【解决方案1】:

最后我听从了 Martin James 的建议,做了这样的事情:

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

Linux 似乎对此非常满意,两个线程都可以毫无问题地完成工作。

【讨论】:

    【解决方案2】:

    将 msgqueue 的线程与管道结合使用可能更简单,因此您可以在串行 tx/rx 中使用 select()/poll()/... 在管道和串行端口上等待线程。

    幸运的是,您甚至不必这样做。事实证明,在 Linux 上(但不是在所有其他 unix 上!)消息队列 ID 也是文件描述符,因此您可以在一次 poll() 调用中等待消息队列和串行端口。您只需要检查哪个处于活动状态即可弄清楚您必须做什么。

    另见Why is there no poll/select-like mechanism for message queues

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-01-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-09-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多