我正在使用
首先我用 write() 发送一个命令。
当使用阻塞模式(规范模式?)时,我只需调用 read() 并等待终止的数据字符串返回。 当使用非阻塞模式(非规范模式?)时,我创建一个循环并在等待数据字符串返回时执行 usleep() (以 ).
这两种方式都按预期工作,但我现在想知道为什么我应该使用其中一种?
就我而言,我需要完整获取的数据字符串才能在我的简单(无线程)程序的其余部分中继续,因此如果我使用阻塞或非阻塞调用似乎并不重要。
如果我的程序使用线程,那么获取数据的线程使用阻塞还是非阻塞似乎仍然不重要?
我能想到的唯一可以从使用非阻塞调用中受益的情况是,如果我正在接收可以部分处理的数据流。
或者在循环中使用 usleep() (或类似的东西)而不是进行阻塞调用有好处吗?
...我现在想知道为什么我应该使用其中之一?
您的问题被表述为阻塞模式与非阻塞模式之间的选择。您还可以将规范模式与阻塞模式相关联,将非规范模式与非阻塞模式相关联。
但规范模式与原始模式与阻塞模式与非阻塞模式是正交的。
请参阅 Linux 阻塞与非阻塞串行读取。
因此,有四种方案需要考虑,但非阻塞模式通常被误用。
就我而言,我需要完整获取的数据字符串才能继续...
这并非您的情况所独有。
大多数二进制协议需要接收整个消息才能完成消息验证,例如计算校验和或 CRC。只有在消息经过验证(即消息包已完整接收)后才会处理消息。
规范模式与原始模式之间的选择通常取决于接收到的数据。也就是说,它是 (ASCII) 文本行吗?
如果接收到的数据不是用 EOL(行尾)字符分隔的 ASCII 编码文本,则规范模式本质上是不切实际的。
使用非规范模式时,不会以任何方式处理数据字节。这种不处理数据的情况对于其他外设来说是典型的。但这是使用(POSIX)串行终端时的一个重大决定/选择!
内核已经在使用中断(也许还有 DMA)和事件驱动的处理程序来有效地处理接收到的数据。当接收到的数据满足串行终端的 termios 标准时,read() 系统调用将被解除阻塞,并通知调度程序该进程已准备好执行。
多处理操作系统依赖进程来共享可用的CPU。典型的过程预计是计算和 I/O 的混合。当执行 I/O 时,该进程不需要使用 CPU。执行该 I/O 的系统时间可以允许另一个进程使用 CPU。
一般来说,用户进程无法改进操作系统提供的阻塞模式的内置事件驱动方案。在循环中使用“
”,可以为已在内核空间中处理的操作添加更多在用户空间中的处理。非阻塞模式增加的复杂性通常会更慢且效率更低,并且永远不会更快或更高效。
非阻塞调用不,您将“
”与原始(或非规范)模式混淆了。原始模式使用 VMIN 和 VTIME 属性,允许控制 read() 返回的时间。 使用非阻塞模式的偶然和特殊原因可能包括:
进程/线程正在多个设备上执行并发 I/O;