C++ 使用select()进行非阻塞串行通信

C++ 使用select()进行非阻塞串行通信,c++,linux,select,serial-port,C++,Linux,Select,Serial Port,我正在做一个项目,在这个项目中,我需要从一个串行端口读写数据,这需要是非阻塞的,因为我不想深入讨论。select函数看起来像我想要使用的,但我正在努力获得一个有效的实现 在open_port中,我定义了端口的设置,并且它是非阻塞的。在otherselect中,我将描述符分配给open_端口并尝试读取。我在函数末尾还有一个1秒的休眠调用,试图避免硬件读取速度过快 在运行时,我会在发送消息之前每秒打印一条消息,因为没有可用的数据。在发送消息之后,它会打印出来,但通常是带有二进制字符的片段。例如,当发

我正在做一个项目,在这个项目中,我需要从一个串行端口读写数据,这需要是非阻塞的,因为我不想深入讨论。select函数看起来像我想要使用的,但我正在努力获得一个有效的实现

在open_port中,我定义了端口的设置,并且它是非阻塞的。在otherselect中,我将描述符分配给open_端口并尝试读取。我在函数末尾还有一个1秒的休眠调用,试图避免硬件读取速度过快

在运行时,我会在发送消息之前每秒打印一条消息,因为没有可用的数据。在发送消息之后,它会打印出来,但通常是带有二进制字符的片段。例如,当发送字缓冲区时,它将打印ffer,后跟一个二进制字符

我几乎没有termios或select的经验,因此任何建议都将不胜感激

#include <iostream>
#include "stdio.h"
#include "termios.h"
#include "errno.h"
#include "fcntl.h"
#include "string.h"
#include "time.h"
#include "sys/select.h"

using namespace std;

int open_port(){
struct termios oldtio,newtio;
int serial_fd;
if ((serial_fd = open("/dev/ttyS0", O_RDWR | O_EXCL | O_NDELAY)) == -1) {
    cout << "unable to open" << endl;
    return -1;
}
if (tcgetattr(serial_fd, &oldtio) == -1) {
    cout << "tcgetattr failed" << endl;
    return -1;
}
cfmakeraw(&newtio); // Clean all settings
newtio.c_cflag = (newtio.c_cflag & ~CSIZE) | CS8 | B115200; // 8 databits
newtio.c_cflag |= (CLOCAL | CREAD);
newtio.c_cflag &= ~(PARENB | PARODD); // No parity
newtio.c_cflag &= ~CRTSCTS; // No hardware handshake
newtio.c_cflag &= ~CSTOPB; // 1 stopbit
newtio.c_iflag = IGNBRK;
newtio.c_iflag &= ~(IXON | IXOFF | IXANY); // No software handshake
newtio.c_lflag = 0;
newtio.c_oflag = 0;
newtio.c_cc[VTIME] = 1;
newtio.c_cc[VMIN] = 60;
if (tcsetattr(serial_fd, TCSANOW, &newtio) == -1) {
    cout << "tcsetattr failed" << endl;
    return -1;
}
tcflush(serial_fd, TCIOFLUSH); // Clear IO buffer
return serial_fd;
}

void otherselect(){
fd_set readfs;
timeval tv;
tv.tv_sec = 1;
tv.tv_usec = 0;
char * buffer = new char[15];
int _fd = open_port();
FD_ZERO(&readfs);
FD_SET(_fd, &readfs);
select(_fd+1, &readfs, NULL, NULL, &tv /* no timeout */);
if (FD_ISSET(_fd, &readfs))
{
    int r = read(_fd, buffer, 15);
    if(r == -1){
        cout << strerror(errno) << endl;
    }
    cout << buffer << endl;
}
else{
    cout << "data not available" << endl;
}
close(_fd);
sleep(1);
}

int main() {
    while(1){
        otherselect();
    }
}

使用read时,不会得到以null结尾的字符串,因此

cout<<buffer<<endl
这显然是个坏主意。 做一个


打印之前。

因为它是C++,你考虑过使用Boosi::Asio吗?你不需要OAN NoBug到你的开放调用,实际上使它不阻塞吗?编辑:IIRC,O_NDELAY只是跳过等待DCD,而O_NONBLOCK实际上只是继续,不等待任何输入。O_NDELAY在fcntl.h中设置为等于O_NONBLOCK,它们是相等的。我还没有研究boost::asio,我现在就要做,但我真的很喜欢被赋予如何处理带有selectread的数据的选项,因为它没有添加终止'\0',所以您的cout如何?这不仅仅是阵列中您需要担心的最后一个单元。您不能假设因为read没有返回-1,所以它一定返回了您要求的全部金额。阅读不是这样的。它可以返回从1到缓冲区大小的任何值,或者0表示EOF,或者-1表示错误。您需要告诉cout仅打印缓冲区中的前r个字符。我不知道怎么做因为我不是C++
buffer[r]='\0'  #(provided r<15)