Linux串行端口:使用超时阻止读取

时间:2022-12-15 15:10:38

I have studied many useful threads and some tutorials, but I'm still having some issues with something that should be very simple. For reference here are some threads that I've perused:

我已经研究了许多有用的线程和一些教程,但我仍然遇到一些应该非常简单的问题。这里参考一些我已经阅读过的主题:

How to implement a timeout in read function call?

如何在读取函数调用中实现超时?

how to open, read, and write from serial port in C

如何在C中从串口打开,读取和写入

At any rate, I have a bit of a problem. My code works fine if I receive data. If I don't, the read() function stalls and the only way to get out of my program is to use kill -9 (NOTE: I use signal handling to signal to the thread reading the serial data to terminate. This is not the culprit, the read() call still stalls even if I have removed my signal handling). What I'm trying to do is to have a read that blocks and reads a chunk at a time (therefore saving CPU usage), however if the read receives no data, I wan't it to timeout.

无论如何,我有点问题。如果我收到数据,我的代码工作正常。如果我不这样做,read()函数会停止并且退出程序的唯一方法是使用kill -9(注意:我使用信号处理来向读取串行数据的线程发出信号以终止。这不是罪魁祸首,即使我已经删除了我的信号处理,read()调用仍然停止。我想要做的是读取一次阻塞和读取一个块(因此节省CPU使用率),但是如果读取没有数据,我就不会超时。

Here are the settings that I'm applying to the port:

以下是我正在应用于端口的设置:

struct termios serial_struct;
serial_struct.c_cflag = B115200 | CS8 | CLOCAL | CREAD;
serial_struct.c_iflag = IGNPAR;
serial_struct.c_oflag = 0;
serial_struct.c_lflag = 0;
serial_struct.c_cc[VTIME] = 1;  // timeout after .1s that isn't working
serial_struct.c_cc[VMIN] = 64;  // want to read a chunk of 64 bytes at a given time

I then set these settings with tcsetattr() and confirm that the port received the settings via tcgetattr(). I'm thinking that my settings may be conflicting, because my reads appear to be blocking and wait until 64 bytes are received, but do not do anything with regards to the timeout. I understand that I can use select() to deal with a timeout, but I'm hoping to avoid the multiple system calls.

然后我使用tcsetattr()设置这些设置,并确认端口通过tcgetattr()接收设置。我认为我的设置可能有冲突,因为我的读取似乎是阻塞并等待直到收到64个字节,但是没有对超时做任何事情。我知道我可以使用select()来处理超时,但我希望避免多次系统调用。

As always, thanks in advance for the help.

一如既往,感谢您的帮助。

1 个解决方案

#1


6  

From man 3 termios:

来自man 3 termios:

MIN > 0; TIME > 0: TIME specifies the limit for a timer in tenths of a second. Once an initial byte of input becomes available, the timer is restarted after each further byte is received. read(2) returns either when the lesser of the number of bytes requested or MIN byte have been read, or when the inter-byte timeout expires. Because the timer is only started after the initial byte becomes available, at least one byte will be read.

MIN> 0; TIME> 0:TIME指定计时器的限制,以十分之一秒为单位。一旦输入的初始字节变为可用,则在接收到每个进一步的字节后重新启动定时器。 read(2)在请求的字节数或MIN字节的较小者或者字节间超时到期时返回。由于定时器仅在初始字节可用后启动,因此将至少读取一个字节。

Note that the timer does not start until at least one byte of data is received. After receiving that first data byte, the read will timeout if there is ever a gap of TIME tenths of a second between receiving consecutive data bytes.

请注意,在收到至少一个字节的数据之前,定时器不会启动。在接收到第一个数据字节后,如果在接收连续数据字节之间存在TIME十分之一秒的间隔,则读取将超时。

#1


6  

From man 3 termios:

来自man 3 termios:

MIN > 0; TIME > 0: TIME specifies the limit for a timer in tenths of a second. Once an initial byte of input becomes available, the timer is restarted after each further byte is received. read(2) returns either when the lesser of the number of bytes requested or MIN byte have been read, or when the inter-byte timeout expires. Because the timer is only started after the initial byte becomes available, at least one byte will be read.

MIN> 0; TIME> 0:TIME指定计时器的限制,以十分之一秒为单位。一旦输入的初始字节变为可用,则在接收到每个进一步的字节后重新启动定时器。 read(2)在请求的字节数或MIN字节的较小者或者字节间超时到期时返回。由于定时器仅在初始字节可用后启动,因此将至少读取一个字节。

Note that the timer does not start until at least one byte of data is received. After receiving that first data byte, the read will timeout if there is ever a gap of TIME tenths of a second between receiving consecutive data bytes.

请注意,在收到至少一个字节的数据之前,定时器不会启动。在接收到第一个数据字节后,如果在接收连续数据字节之间存在TIME十分之一秒的间隔,则读取将超时。