c - 从串行端口读取时如何实现 read() 超时(C/C++)

标签 c unix timeout tty

我正在使用文件描述符和 posix/unix read() 函数从 C++ 中的串行端口读取字节。在此示例中,我从串行端口读取 1 个字节(为了清楚起见,省略了波特率设置和类似内容):

#include <termios.h>
#include <fcntl.h>
#include <unistd.h>

int main(void)
{
   int fd = open("/dev/ttyS0", O_RDWR | O_NOCTTY);
   char buf[1];
   int bytesRead = read(fd, buf, 1);
   close(fd);
   return 0;
}

如果连接到/dev/ttyS0的设备不发送任何信息,程序将挂起。如何设置超时?

我尝试过像这样设置超时:

struct termios options;
tcgetattr(fd, &options);
options.c_cc[VMIN] = 0;
options.c_cc[VTIME] = 10;
tcsetattr(fd, TCSANOW, &options);

我以为应该有 1 秒超时,但这没有什么区别。我想我误解了VMIN和VTIME。 VMIN和VTIME有什么用?

然后我在网上搜索,发现有人在谈论 select() 函数。这是解决方案吗?如果是,如何将其应用于上面的程序以实现 1 秒超时?

感谢任何帮助。预先感谢:-)

最佳答案

是的,使用select(2) 。传入一个文件描述符集,其中仅包含读取集中的 fd 和空写入/异常集,并传入适当的超时。例如:

int fd = open(...);

// Initialize file descriptor sets
fd_set read_fds, write_fds, except_fds;
FD_ZERO(&read_fds);
FD_ZERO(&write_fds);
FD_ZERO(&except_fds);
FD_SET(fd, &read_fds);

// Set timeout to 1.0 seconds
struct timeval timeout;
timeout.tv_sec = 1;
timeout.tv_usec = 0;

// Wait for input to become ready or until the time out; the first parameter is
// 1 more than the largest file descriptor in any of the sets
if (select(fd + 1, &read_fds, &write_fds, &except_fds, &timeout) == 1)
{
    // fd is ready for reading
}
else
{
    // timeout or error
}

关于c - 从串行端口读取时如何实现 read() 超时(C/C++),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23760567/

相关文章:

c# - 设置 DLL 使用超时

android - x 分钟后自动重新打开 android/ios 应用程序

php - 最大执行时间超过 60 秒错误

c - 如何导出 C 表达式 "4 - 2 - 1"?

c - RSA_private_decrypt 失败

linux - SSH 后的初始欢迎消息(横幅)不允许命令正确执行

c - Perl 进程卡住 «*** glibc detected *** perl : corrupted double-linked list: 0x0000000001474b40 ***» - how can I make it terminate?

xcode - 我如何验证死代码是否已从二进制文件中删除?

C 抽象限制

java - 找不到 sun.nio.ch.FileChannelImpl.read 的实现