【发布时间】:2021-10-11 16:29:25
【问题描述】:
我试图了解VMIN 和VTIME 如何控制read() posix 调用的阻塞行为。
在我的示例中,我已将 VTIME 设置为 10(并且也尝试了其他组合),这应该会阻止读取 1 秒,直到它被解锁,是吗?这是我的理解,但事实并非如此。
我在我的主机上打开了最低限度,我看到read() 只会在我在 minicom 中点击 enter 后立即解锁,而不是等待 1 秒解锁。
我的理解不正确吗?如果不是这样,可能有什么问题?
int Serial_Open(char *port)
{
int serial_port = open(port, O_RDWR);
struct termios tty;
// Read in existing settings, and handle any error
if(tcgetattr(serial_port, &tty) != 0)
{
printf("Error from tcgetattr: %s\n", strerror(errno));
}
tty.c_cflag &= ~PARENB; // Clear parity bit, disabling parity (most common)
tty.c_cflag &= ~CSTOPB; // Clear stop field, only one stop bit used in communication (most common)
tty.c_cflag &= ~CSIZE; // Clear all bits that set the data size
tty.c_cflag |= CS8; // 8 bits per byte (most common)
tty.c_cflag &= ~CRTSCTS; // Disable RTS/CTS hardware flow control (most common)
tty.c_cflag |= CREAD | CLOCAL; // Turn on READ & ignore ctrl lines (CLOCAL = 1)
tty.c_lflag &= ~ICANON;
tty.c_lflag &= ~ECHO; // Disable echo
tty.c_lflag &= ~ECHOE; // Disable erasure
tty.c_lflag &= ~ECHONL; // Disable new-line echo
tty.c_lflag &= ~ISIG; // Disable interpretation of INTR, QUIT and SUSP
tty.c_iflag &= ~(IXON | IXOFF | IXANY); // Turn off s/w flow ctrl
tty.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL); // Disable any special handling of received bytes
tty.c_oflag &= ~OPOST; // Prevent special interpretation of output bytes (e.g. newline chars)
tty.c_oflag &= ~ONLCR; // Prevent conversion of newline to carriage return/line feed
tty.c_cc[VTIME] = 10; // Wait for up to 1s, returning as soon as any data is received.
tty.c_cc[VMIN] = 0;
cfsetspeed(&tty, B115200);
if (tcsetattr(serial_port, TCSANOW, &tty) != 0)
{
printf("Error tcsetattr %s\n", strerror(errno));
}
return serial_port;
}
int main(void)
{
char buffer[100];
int ret;
int fd = Serial_Open("/dev/ttyUSB4");
while(1)
{
ret = read(fd, buffer, sizeof(buffer));
if (ret <= 0)
{
printf ("No data or error\n");
}
else
{
printf ("Rxd data: %s\n", buffer);
}
}
return 1;
}
【问题讨论】:
-
"...应该阻止读取 1 秒,直到解锁,是吗?这是我的理解..." -- 不。您的理解不正确。阅读 man 页面了解 termios。顺便说一句,您的代码不会像发布的那样编译: Serial_Open() 被声明为 void 例程。 read() 不返回字符串,因此您的 printf() 可以显示垃圾(以及陈旧数据)。
-
我读到这个 -> blog.mbedded.ninja/programming/operating-systems/linux/… - 它说
VMIN=0, VTIME>0是任何数量的字符的阻塞读取,超时由VTIME设置的任何值给出,在我的情况下是 1s .基本上read()阻塞,直到任何数量的数据可用或发生超时。那么如果超时时间为1s,还没有收到数据,是不是应该在之后解除阻塞呢? -
再来一次:阅读 man 页面了解 termios。不要引用或依赖一些试图用更少的词来描述 man 页面的不知名人士。即使在快速修复之后,您的代码仍然会损坏。
-
"当调用 read(2) 时启动计时器。当至少一个字节数据可用时,或者当计时器到期时,read(2) 返回。"。这对我来说仍然很熟悉。我是否也错过了其他东西?
-
您写道,您认为将
VTIME设置为 10 应该“阻止读取 1 秒,直到它被解除阻止”。即使我们将此与从您的代码中提取的信息结合起来,您也将VMIN设置为零并禁用规范模式,这听起来不正确。该配置应导致read()阻止最多 秒,假设 尚未读取任何数据。可能会有不到一秒的阻塞,读也不一定会阻塞。也许这就是你想要表达的理解,但我并没有这样理解。
标签: c linux serial-port posix uart