linux中串口描述符块的'close'功能

时间:2013-01-10 10:08:58

标签: linux serial-port embedded-linux

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

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

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

我尝试在关闭之前做tcflush(uart->fd, TCOFLUSH)而没有任何影响。

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

3 个答案:

答案 0 :(得分:2)

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

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

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

答案 1 :(得分:0)

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

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);
}
...

答案 2 :(得分:0)

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

  

closing_wait 延迟                 指定内核应等待从中传输数据的时间量(以百分之一秒为单位)   串口同时                 关闭港口。如果指定“none”,则不会发生延迟。如果指定“无限”,则内核将等待   无限期地                 要传输的缓冲数据。默认设置为3000或30秒延迟。通常是默认值   适合大多数人                 设备。如果选择了太长的延迟,那么如果串口是串口,则串口可能会长时间挂起   没有连接,和                 有待处理的数据,已关闭。如果选择的延迟太短,则存在一些传输数据的风险   输出完全。                 如果设备非常慢,就像绘图仪一样,closing_wait可能需要更大。

使用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中启动时发出此命令,或者您的发行版用于配置端口的任何脚本。