У меня есть программа, которая читает и пишет в последовательный порт. У меня есть ветка для чтения, которая считывает данные и передает информацию в общую память. Поток читателя должен спать, пока данные не будут доступны. Итак, я хочу сделать read()
системный вызов для блокировки вызывающего потока. Учитывая справочные страницы, если вы не предоставите O_NONBLOCK
в open
, read
должен всегда блокировать. Но у меня есть активная тема, которая в нем read
возвращается -1
непрерывно. ТАКЖЕ меняется VTIME
а также VMIN
не имеет значения. Вот как открывается порт:
fd = open(portName.str().c_str()/*/dev/ttyS2*/, O_RDWR | O_NOCTTY);
if (fd < 0) // if open is not successful
{
cerr << ERROR << "Unable to open `" << portName << "'." << endl;
return false;
}
else
{
cout << INFO << "Port " << portName.str() << " successfully opened."<< endl;
cout << INFO << "Configuring port..." << endl;
fcntl(fd, F_SETFL,0);
struct termios port_settings; // structure to store the port settings in
cfsetispeed(&port_settings, B38400); // set baud rate
cfsetospeed(&port_settings, B38400); // set baud rate
port_settings.c_cflag |= CLOCAL | CREAD;
port_settings.c_cflag &= ~CRTSCTS; // disable H/W flow control
port_settings.c_lflag &= ~( ISIG | // disable SIGxxxx signals
IEXTEN | // disable extended functions
ECHO | ECHOE); // disable all auto-echo functions
port_settings.c_lflag &= ~ICANON ; // raw mode
port_settings.c_oflag &= ~OPOST; // raw output
port_settings.c_iflag &= ~(IXON | IXOFF | IXANY); // disable S/W flow control;
// Following values do not change timout in runtime:
port_settings.c_cc[VTIME] = 2; // wait 0.2 second to get data -
port_settings.c_cc[VMIN] = 0;
port_settings.c_cflag = (port_settings.c_cflag &= ~CSIZE) | CS8; // set data byte size
port_settings.c_cflag &= ~CSTOPB; // set stop bit 1
port_settings.c_cflag &= ~PARENB; // set no parity
port_settings.c_iflag |= IGNPAR; // ignore parity
port_settings.c_iflag &= ~(INPCK | ISTRIP | PARMRK);
// Set
if (tcsetattr(fd, TCSANOW, &port_settings) < 0)
{
cerr << ERROR << "Unable to configure serial port." << endl;
return false;
}
else
{
cout << INFO << "Port `" << portName.str()
<< "' configuration was successful." << endl;
}
И в теме читателя:
byte buffer[256];
while (true)
{
int packetSize = read(fd, buffer, 256);
if (packetSize > 0)
{
// use data - this code is never run
}
else
{
// print error - we're always here. no matter how long timout is
}
}
Несколько вещей, чтобы рассмотреть здесь.
Во-первых, чтение может вернуться по ряду причин. Прерывания любого вида приведут к разблокировке чтения и возврату -1, также может быть проблема с файлом. Проверьте переменную errno для получения дополнительной информации о том, почему она возвращает -1. Описание возможных ошибочных значений находится в читать справочную страницу
Во-вторых, после того, как вы решили вышеупомянутое, когда данные доступны, чтение не гарантирует вам всего сетевого пакета за одно чтение, поэтому вам может потребоваться повторная сборка из нескольких операций чтения.
Других решений пока нет …