简体   繁体   中英

Force read system call to block

I have a program that reads from and writes to serial port. I have a reader thread that reads data and supplies informations to shared memory. The reader thread should sleep until data is available. So I want to make read() system call to block calling thread. Considering man pages, unless you supply O_NONBLOCK to open , read should always block. But I have an active thread which in it read returns -1 continuously. ALso changing VTIME and VMIN does not make a difference. This is how port is opened:

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;
        }

And in reader thread:

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
    }
 }

A few things to consider here.

First, read can return for a number of reasons. Interrupts of any kind will cause read to unblock and return -1, also there could be an issue with the file. Check errno variable for more information on why it is returning -1. Description of possible errno values are in the read man page

Second, after you've solved the above, when data is available read is not guaranteed to give you an entire network packet in a single read, so you might need to reassemble from multiple reads.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM