最近我发现了一个对我来说很新的问题,我很感激建议。我正在使用termios函数在Linux上进行串行通信。我实际上不使用真正的串行端口,而是使用虚拟小工具串行驱动程序/dev/ttyGS0
。文件描述符以非阻塞方式打开。
我的程序会定期生成数据并将其发送到/ dev / ttyGS0。如果另一端读取它没有信息。如果没有,则一些内部fifo填满并写入返回“将阻止”错误。到目前为止一切顺利,我对此没有任何问题。
问题是,当我想用填充的fifo关闭这样的文件描述符时,关闭功能块!不是无限期,但是大约10秒钟。
我尝试在关闭之前做tcflush(uart->fd, TCOFLUSH)
而没有任何影响。
这对我来说是一种奇怪的行为,我没有找到任何描述,这种关闭可能会阻止。有什么方法可以避免这种情况吗?或者至少减少这个超时?我应该在哪里寻找这个超时? VTIME属性对此也没有影响。
答案 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中启动时发出此命令,或者您的发行版用于配置端口的任何脚本。