【问题标题】:Force read system call to block强制读取系统调用阻塞
【发布时间】:2023-03-09 10:42:01
【问题描述】:

我有一个读取和写入串行端口的程序。我有一个读取器线程,它读取数据并将信息提供给共享内存。读取器线程应该休眠,直到数据可用。所以我想进行read() 系统调用来阻止调用线程。考虑手册页,除非您将O_NONBLOCK 提供给open,否则read 应始终阻止。但我有一个活动线程,其中read 连续返回-1。还更改 VTIMEVMIN 并没有什么不同。端口是这样打开的:

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

【问题讨论】:

    标签: c++ serial-port system-calls


    【解决方案1】:

    这里有几件事要考虑。

    首先,read 可能出于多种原因返回。任何类型的中断都会导致读取解除阻塞并返回 -1,文件也可能存在问题。检查 errno 变量以获取有关它返回 -1 的原因的更多信息。可能的 errno 值的描述在 read man page

    其次,在你解决了上述问题之后,当数据可用时,读取并不能保证在一次读取中给你一个完整的网络数据包,所以你可能需要从多次读取中重新组装。

    【讨论】:

    • 感谢您的回复。我用perror 测试,结果是Invalid argument
    • 这意味着fd 不是一个有效的文件描述符。
    • ...而 errno 是 EBUSY (16)
    • 是的,听起来像是一个糟糕的描述符。您应该查看如何将描述符从一个线程传递到另一个线程,以确保它在读取器线程中仍然有效。
    • 嗯...我不知道如何在线程之间传递描述符。我要去搜索一下。谢谢
    猜你喜欢
    • 1970-01-01
    • 2020-09-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多