4

最近我发现了一个对我来说很新的问题,我会很感激建议。我正在使用 termios 函数在 Linux 上进行串行通信。我实际上不使用真正的串口,而是使用虚拟小工具串行驱动程序/dev/ttyGS0。文件描述符以非阻塞方式打开。

我的程序会定期生成数据并将其发送到 /dev/ttyGS0。如果另一端读取它,则没有信息。如果没有,则某些内部 fifo 会填满并写入返回“将阻塞”错误。到目前为止一切顺利,我对此没有任何问题。

问题是,当我想用​​填充的 fifo 关闭此类文件描述符时,关闭功能块!不是无限期的,而是大约 10 秒。

我试着tcflush(uart->fd, TCOFLUSH)在关闭之前做,没有任何效果。

这对我来说是如此奇怪的行为,我没有找到任何描述,关闭可能会阻塞。有什么办法可以避免这种情况吗?或者至少减少这个超时?我应该在哪里寻找这个超时?VTIME 属性对此也没有影响。

4

3 回答 3

2

正如 Amardeep 提到的,close() 调用由驱动程序处理。Close 本身始终是一个阻塞调用,但通常它是一个快速调用。

因此,答案是延迟特定于虚拟小工具驱动程序。我没有帮助的经验。

关闭文件有多重要?如果延迟是一个主要问题并且需要关闭文件(例如在长时间运行的进程中避免文件描述符泄漏),那么关闭可能需要在单独的线程中调用。显然,最好的答案是特定于该驱动程序的答案。也许那里的研究可能会产生答案,例如清除虚拟设备状态的 ioctl() 调用。

于 2013-08-21T18:41:36.990 回答
1

您可能需要配置端口的 closing_wait 参数。从setserial手册:

关闭等待延迟 指定内核在关闭端口时应等待从串行端口传输数据的时间量(以百分之一秒为单位)。如果指定“none”,则不会发生延迟。如果指定了“infinite”,内核将无限期地等待缓冲数据的传输。默认设置为 3000 或 30 秒延迟。此默认值通常适用于大多数设备。如果选择了太长的延迟,那么当一个未连接且有数据未决的串口关闭时,串口可能会挂起很长时间。如果选择的延迟太短,则存在一些传输数据被完全输出的风险。如果设备速度极慢,

使用 setserial 检查您的端口的参数:

$ setserial -g -a /dev/ttyS0
/dev/ttyS0, Line 0, UART: 16550A, Port: 0x03f8, IRQ: 4
        Baud_base: 115200, close_delay: 50, divisor: 0
        closing_wait: 3000
        Flags: spd_normal skip_test

就我而言,故障设备没有收到我发送的最后一个字节,因此关闭端口总是需要 30 秒。您可以使用 setserial 更改此超时,例如,更改为 1 秒:

$ sudo setserial /dev/ttyS0 closing_wait 100

当然,您可能希望在启动时在 /etc/rc.local 或您的发行版用于配置端口的任何脚本中发出此命令。

于 2017-12-13T18:33:24.173 回答
0

我遇到了同样的问题,在我的情况下,在关闭设备之前禁用流量控制有帮助。您可以使用以下函数执行此操作:

int set_flowcontrol(int fd, int control) 
{
    struct termios tty;
    memset(&tty, 0, sizeof tty);
    if (tcgetattr(fd, &tty) != 0) 
    {
        perror("error from tggetattr");
        return -1;
    }

    if(control) tty.c_cflag |= CRTSCTS;
    else tty.c_cflag &= ~CRTSCTS;

    if (tcsetattr(fd, TCSANOW, &tty) != 0)
    {
        perror("error setting term attributes");
        return -1;
    }
    return 0;
}

只需在关闭之前调用它:

...
rc = set_flowcontrol(fd, 0);
if (rc != 0)
{
    perror("error setting flowcontrol: ");
    exit(-1);
}

rc = close(fd);
if (rc != 0)
{
    perror("error closing fd: ");
    exit(-1);
}
...
于 2016-10-04T13:00:22.630 回答