【问题标题】:OpenBSD serial I/O: -lpthead makes read() block forever, even with termios VTIME set?OpenBSD 串行 I/O:-lpthead 使 read() 永远阻塞,即使设置了 termios VTIME?
【发布时间】:2013-04-11 23:13:14
【问题描述】:

我有一个通过 termios 串行 API 使用的 FTDI USB 串行设备。我设置了端口,以便它在半秒内调用 read() 超时(通过使用 VTIME 参数),这在 Linux 和 FreeBSD 上都有效。然而,在 OpenBSD 5.1 上,read() 调用会在没有数据可用时永远阻塞(见下文。)我希望 read() 在 500 毫秒后返回 0。

谁能想到 termios API 在 OpenBSD 下的行为会有所不同,至少在超时功能方面?

编辑:无超时问题是由链接到 pthread 引起的。无论我是否实际使用任何 pthread、互斥锁等,简单地链接到该库都会导致 read() 永远阻塞,而不是根据 VTIME 设置超时。同样,这个问题只在 OpenBSD 上出现——Linux 和 FreeBSD 可以正常工作。

if ((sd = open(devPath, O_RDWR | O_NOCTTY)) >= 0)
{
  struct termios newtio;
  char input;

  memset(&newtio, 0, sizeof(newtio));

  // set options, including non-canonical mode
  newtio.c_cflag = (CREAD | CS8 | CLOCAL);
  newtio.c_lflag = 0;

  // when waiting for responses, wait until we haven't received
  // any characters for 0.5 seconds before timing out
  newtio.c_cc[VTIME] = 5;
  newtio.c_cc[VMIN] = 0;

  // set the input and output baud rates to 7812
  cfsetispeed(&newtio, 7812);
  cfsetospeed(&newtio, 7812);

  if ((tcflush(sd, TCIFLUSH) == 0) &&
      (tcsetattr(sd, TCSANOW, &newtio) == 0))
  {
    read(sd, &input, 1); // even though VTIME is set on the device,
                         // this read() will block forever when no
                         // character is available in the Rx buffer
  }
}

【问题讨论】:

  • 你使用的是-pthread还是-lpthread?
  • 对不起,我又看到标题了;)
  • 你能在我们切换到默认rthreads的OpenBSD 5.2上试试吗?在我的 5.3 系统上,您的示例不会阻塞。 obsd/amd64.
  • 清零termios 结构不是正确的初始化方法。您应该调用tcgetattr(),然后修改 标志。您正在使用 POSIX 接口,并且您应该遵循他们的可移植性实践。见Serial Programming Guide for POSIX Operating Systemscfset?speed() 的论点也看起来很假; “波特率”不是数值,而是编码值。
  • 对 rthreads 的更改显然很重要——代码在 OpenBSD 5.2 上可以正常工作!另外,我将更改termios struct init 以便它首先调用tcgetattr(),但我看不出我可以做些什么来将参数更改为cfset?speed()——在7812 波特中没有编码值termios 标头。

标签: serial-port pthreads openbsd


【解决方案1】:

来自 termios 手册页:

 Another dependency is whether the O_NONBLOCK flag is set by open() or
 fcntl().  If the O_NONBLOCK flag is clear, then the read request is
 blocked until data is available or a signal has been received.  If the
 O_NONBLOCK flag is set, then the read request is completed, without
 blocking, in one of three ways:

       1.   If there is enough data available to satisfy the entire
            request, and the read completes successfully the number of
            bytes read is returned.

       2.   If there is not enough data available to satisfy the entire
            request, and the read completes successfully, having read as
            much data as possible, the number of bytes read is returned.

       3.   If there is no data available, the read returns -1, with errno
            set to EAGAIN.

你能检查一下是不是这样吗? 干杯。

编辑:OP 将问题追溯到导致读取函数阻塞的 pthread 链接。通过升级到 OpenBSD >5.2,这个问题通过将新的 rthreads 实现更改为 openbsd 上的默认线程库而得到解决。更多信息guenther@ EuroBSD2012 slides

【讨论】:

  • 我发现我的无超时问题是由链接到 pthread 库(我需要它)引起的。我创建了一个独立的测试程序,仅使用上面显示的代码和超时仅当我构建它没有链接到 pthread 时才有效(无论我是否实际使用任何 pthread 设备。)为什么会这样?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-03-27
  • 2015-02-24
相关资源
最近更新 更多