使用 VTIME 和 read() 的 POSIX 行为
POSIX behaviour with VTIME and read()
在网上花了几个小时研究这个之后,我仍然不太清楚VTIME
和read(int fildes, void *buf, size_t nbyte);
是如何一起工作的。在我看来,一旦read()
得到一个字节,它就会忽略VTIME
. 仅当未读取任何字节时,才遵守VTIME
。
如果我没看错,这里的解释似乎证实了这一点:
VMIN = 0 且 VTIME> 0 这是一个纯粹的定时阅读。如果数据在输入队列中可用,则会将其传输到调用方的缓冲区,最大为 nbytes,并立即返回到调用方。否则,驱动程序将阻止,直到数据到达,或者当 VTIME 十分之一从呼叫开始过期时。如果计时器过期时没有数据,则返回零。单个字节足以满足此读取调用,但如果输入队列中有更多可用字节,则会将其返回给调用方。请注意,这是一个整体计时器,而不是字符间计时器。
有没有办法让read()
仅在满足nbyte
或在最后一个字节后达到VTIME
时才返回?
VTIME
和read()
会这样做似乎有点奇怪。为什么它不尝试在超时之前读取nbytes
?
例如,在下面的代码中,read()
不会等待 10 秒就返回。如果未发生写入,则会发生。
int main (void) {
int usbSerial;
struct termios options;
std::string port = "/dev/tty.usb001";
usbSerial = open(port.c_str(), O_RDWR| O_NOCTTY | O_NONBLOCK);
// Check if unopen
if(usbSerial == -1) {
printf("Error: Unable to open %sn", port.c_str());
}
else { // Set to blocking
fcntl(usbSerial, F_SETFL, 0);
printf("Connection to serial device established.n");
}
// Set port settings
tcgetattr(usbSerial, &options); // read old port settings
cfsetispeed(&options, B9600);
cfsetospeed(&options, B9600);
options.c_cflag &= ~PARENB; // set no parity, 1 stop bit, data bits
options.c_cflag &= ~CSTOPB;
options.c_cflag &= ~CSIZE;
options.c_cflag |= CS8;
options.c_cflag &= ~CRTSCTS; // no flow control.
options.c_cflag |= CREAD | CLOCAL; // turn on READ & ignore ctrl lines
options.c_cc[VMIN] = 0;
options.c_cc[VTIME] = 100;
// Flush port and then apply new options
tcflush(usbSerial, TCIOFLUSH);
if (tcsetattr(usbSerial, TCSANOW, &options) != 0) { // TCSANOW == make option change immediately
printf("Error %i from tcsetattr.n", errno);
}
// write
unsigned char message[] = {0x03, 0x05, 0x01, 0x01, 0x04};
ssize_t n = write(usbSerial, &message, sizeof(message)/sizeof(message[0]));
unsigned char buffer[64] = {};
tcdrain(usbSerial);
ssize_t readChars = read(usbSerial, &buffer, 10);
printf("Done.n");
}
我相信你说的是正确的:
在我看来,一旦 read() 获得一个字节,它就会忽略 VTIME。
read()
的返回值:
成功后,将返回读取的字节数(零表示文件结束),并且文件位置将提前此数字。 如果此数字小于请求的字节数,则不是错误;例如,这可能是因为现在实际可用的字节较少(可能是因为我们接近文件末尾,或者因为我们从管道或终端读取),或者因为 read() 被信号中断。链接
您可能需要循环,可能是类似(未经测试的):
int totalNeeded = 10;
int remaining = 10;
while (remaining > 0){
ssize_t readChars = read(usbSerial, &buffer[totalNeeded - remaining], remaining);
if (readChars > 0){
remaining -= readChars;
}
else{
// handle error or EOF
}
}
不确定您需要如何处理部分读取,尤其是因为O_NONBLOCK
,但我认为 VTIME 和 read()
之间的行为交互受read()
支配。
- 理解boost::asio-async_read在无需读取内容时的行为
- 模板-模板参数推导:三个不同的编译器三种不同的行为
- arr[-1]在c++中的奇怪行为
- 继承期间显示未知行为的子类
- 如何在c++中使用引用实现类似python的行为
- G锁定铸造到基础上会释放模拟行为
- 在C++中对T*类型执行std::move的意外行为
- std::当在256字节边界上写入整数时,流的奇怪行为
- 不知道某个东西是否被忽略会引入未定义的行为吗
- 奇怪的构造函数行为
- 重载运算符new[]的行为取决于析构函数
- 不同语言中相同代码的不同行为
- 处理除以零会导致<csignal>意外行为
- 试图理解类对象的行为
- c++11评估顺序(未定义的行为)
- 从结构寻址时,MMAP变量的行为很奇怪
- 我可以做些什么来消除或最小化这种将提供相同功能和行为的代码重复
- 读取文件时运行时的未知行为
- strncpy之后的char数组的错误行为
- 使用 VTIME 和 read() 的 POSIX 行为