输入中固定数据的非阻塞读取

Non blocking read with fixed data in input

我想使用串行端口与另一个设备 txdev 通信,问题是 txdev 正在异步发送数据,我不希望 read 函数阻塞,好消息是 txdev 正在发送固定大小的数据,但我不知道如何使用这个技巧。 我正在做的是以下内容:

fd = open(DEVICE_NAME, O_RDWR | O_NOCTTY);
bzero(&termios_p, sizeof(termios_p));
termios_p.c_cflag = CS8|CSTOPB|CLOCAL|CREAD;
termios_p.c_iflag = IGNPAR;
termios_p.c_oflag  = 0;
termios_p.c_lflag = ~ICANON;
termios_p.c_cc[VMIN]=DATA_LENGTH;
termios_p.c_cc[VTIME]=10;

cfsetispeed(&termios_p, BAUDRATE);
cfsetospeed(&termios_p, BAUDRATE);  

tcflush(fd, TCIFLUSH);
tcsetattr(fd,TCSANOW,&termios_p);

来自 this post 我不明白这会导致读取被阻塞 VTIME = 0 也被阻塞。

谁能帮我找出解决方案我认为我必须使用中断处理程序而不是 read 你同意吗?

第二个问题:由于发送方无法与接收方同步,是否有一个中断处理程序将接收到的数据存储在指定的缓冲区中(我不明白规范模式是这种情况,但非规范模式不是)或者这只在达到 read 功能时才完成,如果我错了请纠正我

像往常一样,非常感谢。

I want use serial port to communicate with another device txdev, the problem is that txdev is sending data asynchronously and i don't want the read function to block,

您似乎误解了 Linux 应用程序应该如何读取和写入串口。所有数据都在您的程序和 UART 之间进行缓冲。您的程序不必总是准备好读取数据,因为它来自网络。 OS(特别是 UART 设备驱动程序和包含线路规程的 tty 子系统)执行此操作,并为您的程序缓冲数据。

RS-232 根据定义是一种异步通信 link。 characters/bytes 可以随时传输。消息包会在任何时间点到达,因此应用程序将不得不等待组成消息包的字节。这是使用阻塞读取的情况。

接收串口数据的典型问题是如何对接收到的数据进行词法扫描,从而识别出一个完整的报文包。文本消息(规范模式)简单地使用 ASCII 行控制字符来分隔 messages/lines。即使是固定长度的数据包也需要验证(以确保消息实际上从正确的字节开始)。参见 this example of scanning fixed-length packets

i think i have to use interrupt handler instead of a read do you agree ?

不,UART 设备驱动程序已经在为其中断服务(或使用 DMA)以捕获从串行 link 接收到的每个字节。

Since a sender can't get synchronized with the receiver is there an interrupt handler that stores the received data on specified buffer (i undrestand that this is the case for Canonical mode but not in Non canonical mode) or this is only done when read function is reached,

不需要接收端串口与发送串口"synchronize"在字节级别。 RS-232是一种异步通信link:发送方can/will随时发送一个character/byte,另一端必须准备好接收(除非有硬件或软件流控)到位)在设备驱动程序级别(而不是应用程序)。

OS总是缓冲这个接收到的数据。应用程序的 read() 系统调用仅仅是从系统缓冲区到用户缓冲区的复制操作。此复制操作适用于规范和非规范模式。

"Getting synchronized" 通常是协议要在消息或数据包级别解决的问题。主从是定义串行link协议的常见配置。主端向从端发送查询消息。从站必须始终准备好接收查询。从端可以响应事务请求或数据捕获或其他任何内容,或者 NAK 消息以指示它对主端没有任何信息。此请求-响应对话框旨在控制或调整两个单元之间的数据流(和处理负载)。

附录

what i'am planing to do is actually a blocking read (VTIME =0 VMIN = DATA_LENGTH) in an infinite loop

大概您将始终在发送设备之前启动您的程序,以便第一个传输的 DATA_LENGTH 将与程序的第一个读取对齐。

在理想或受监控的情况下,这可能在大多数情况下都有效。
但对于工业 24/7 应用程序,丢失消息帧对齐的可能性是真实存在的(例如,发送设备在传输过程中重新启动),因此没有主动手段来验证和重新获得消息帧对齐的方案是不合适的。

IOW 串行端口的原始 read() 可能不会 return 缓冲区中的对齐消息(即 buf[0] 可能不包含第一个字节消息)。
具有非零 VTIME 的小得多的 VMIN 是典型的 termios 配置,其前提是串行 link 在每条消息后空闲(短时间间隔)。
但是代码应该很健壮,可以在读取时处理 any/all 消息片段。因此,可能需要不止一个 read() 来重建整个消息。