linux - TTY 输入队列太慢无法返回数据

标签 linux serial-port embedded-linux tty

我最近注意到我的系统(运行在 AT91SAM9G15 上)有一个非常奇怪的行为:尽管我一直在读取串行端口,但 TTY 驱动程序有时需要 1.2 秒才能从输入队列传送数据。 事情是:我没有丢失任何数据,只是需要太多调用才能读取数据。

也许我的代码可以帮助解释这个问题。

首先,我设置我的串口:

/* 8N1 */
tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS8;
/** Parity bit (none) */
tty.c_cflag &= ~(PARENB | PARODD);
/** Stop bit (1)*/
tty.c_cflag &= ~CSTOPB;
/* Noncanonical mode */
tty.c_lflag = 0;
tty.c_oflag = 0;
tty.c_cc[VMIN] =  0;
tty.c_cc[VTIME] = 0;

稍后,select 被调用:

s_ret = select(rfid_fd + 1, &set, NULL, NULL, &port_timeval);

所以 read() 可以发挥它的魔力:

...
 if ((rd_ret = read(rfid_fd, &recv_buff[u16_recv_len], (u16_req_len - u16_recv_len))) > 0)
...

紧接着,如果我继续读取串行端口 15 秒,有好几次我都看不到数据,而且我知道准时到达(带有时间戳)的数据来晚了。从输入队列中获取数据的延迟可能从 300 毫秒到 1.5 秒不等。

我已经尝试了所有我能想到的设置。现在很棘手,因为我不知道 at91 UART 驱动程序是否没有向 tty 驱动程序传送数据,或者 tty 驱动程序没有获取它?这是哪个?

如有任何帮助,我们将不胜感激。

最佳答案

设置端口标志的正常过程是读取 termios 结构,保存它以供以后恢复,修改(在它的副本中)您想要更改的标志,然后执行 tcsetattr() 调用。您已经初始化了 c_lflag = 0;,这可能会对您的问题产生一些次要影响。

接下来您必须考虑阅读有关 VMINVTIME 元素的文档。将两者都设置为 0 会使驱动程序成为非阻塞设备,因此您将进入一个循环,试图读取缓冲区中应该包含的任何内容。但在这样做之前,请三思,您有两个线程争相将字符放入缓冲区(您的进程试图从缓冲区中获取它,而驱动程序中断例程试图将刚刚读取的字符放入)而没有休息。等待一个字符可用会更好(可能这就是问题所在),将 VMIN 设置为 1 并将 VTIME 设置为 0。这使得驱动程序在一个字符可用时立即唤醒您的进程,并且可能更接近您想要的。

经过所有这些猜测,您还没有发布任何可用于检查您所说内容的可重现代码,因此这是我们能为您提供的最多帮助。

关于linux - TTY 输入队列太慢无法返回数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42123077/

相关文章:

memory-management - 什么是VM_BUG_ON_PAGE(PageLRU(page)|| PageUnevictable(page))?

linux - google_accounts_daemon[1140] : Full path required for exclude: net[4026532634]

linux - 删除 AWS 上的旧快照

java - 如何使用java初始化串口?

linux - 如何在X11中创建圆角矩形窗口

linux-kernel - Linux USB 驱动程序 : Interrupt URBs

linux - Catalina.out 未通过 bash 脚本在编辑后登录

c# - 如何在 Linux 上使用 Mono 获取文件信息

c# - 通过 MSComm1 发送 ctrl-E

python - ValueError : "port" must be None or a string, 不是 <class 'int' >