Linux中如何解决串口读取阻塞问题

4
我使用select()调用在专用线程中无限期地阻塞串口fd,该线程不断读取数据。除非我设置超时等,否则我无法想出一种从我的select调用中唤醒的方法。在套接字编程中,您可以使用shutdown()调用来唤醒任何被阻塞在select()上的线程。
但是,在串口方面,我没有看到任何类似物。在我的“读者”线程被select()阻塞的同时,从另一个线程调用close()似乎在POSIX上没有定义良好的行为。特别是在Linux上,调用close()对fd没有任何影响,不会唤醒任何已在该fd上调用select()的线程。参见(http://linux.die.net/man/2/select):如果在另一个线程中关闭正在由select()监视的文件描述符,则结果是未指定的。在某些UNIX系统上,select()解除阻塞并返回,指示文件描述符已准备就绪(随后的I/O操作可能会因错误而失败,除非在select()返回和执行I/O操作之间重新打开了另一个文件描述符)。在Linux(和其他一些系统)上,在另一个线程中关闭文件描述符对select()没有影响。总之,任何依赖于此场景中特定行为的应用程序都必须被认为是有缺陷的。

在Linux中,是否有可能唤醒无限期阻塞在串口文件描述符上的线程?如果可以,如何实现?

编辑:

有一种“hack”方法可以通过使用带有sleep()的循环调用select()来绕过此问题(尽管这并不理想,因为现在唤醒请求和线程实际唤醒之间存在延迟)。在系统方面,循环调用select是否会有任何不利影响?


Select 调用应该在任何集合中的任何描述符上发生事件时立即唤醒。也许您需要将描述符放入异常集合中? - Some programmer dude
我会尝试一下,因为现在我只有它在读取文件描述符中,但根据我更新的答案中的描述,似乎它不太可靠。 - Prismatic
编辑 - 即使将fd添加到异常集中,仍然没有任何反应。 - Prismatic
1个回答

3

两种典型的解决方案:

  1. 创建管道并将其添加到选择队列中。一旦您通过此管道发送数据 - 选择便会退出。

  2. 如果唤醒所有线程不是问题,您可以发送信号。


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