C 拔下并重新插入连接器后,无法从串行设备读取数据

C 拔下并重新插入连接器后,无法从串行设备读取数据,c,linux,serial-port,posix,C,Linux,Serial Port,Posix,我有一个Linux应用程序,应该从串行设备读取/dev/ttyS0。串行设备以以下方式打开: // Open the serial port if((serial_device = open("/dev/ttyS0", O_RDWR | O_NOCTTY)) < 0){ fprintf(stderr, "ERROR: Open\n"); exit(EXIT_FAILURE); } // Get serial device attributes if(tcgetattr(s

我有一个Linux应用程序,应该从串行设备读取
/dev/ttyS0
。串行设备以以下方式打开:

// Open the serial port
if((serial_device = open("/dev/ttyS0", O_RDWR | O_NOCTTY)) < 0){
    fprintf(stderr, "ERROR: Open\n");
    exit(EXIT_FAILURE);
}

// Get serial device attributes
if(tcgetattr(serial_device,&options)){
    fprintf(stderr, "ERROR: Terminal Get Attributes\n");
    exit(EXIT_FAILURE);
}

cfsetspeed(&options,speed);             // Set I/O baud rates
cfmakeraw(&options);                    // Set options to transceive raw data
options.c_cflag |= (CLOCAL | CREAD);    // Enable the receiver and set local mode
options.c_cflag &= ~CSTOPB;             // 1 stop bit
options.c_cflag &= ~CRTSCTS;            // Disable hardware flow control
options.c_cc[VMIN]  = 1;                // Minimum number of characters to read
options.c_cc[VTIME] = 10;               // One second timeout

// Set the new serial device attributes
if(tcsetattr(serial_device, TCSANOW, &options)){
    fprintf(stderr, "ERROR: Terminal Set Attributes\n");
    exit(EXIT_FAILURE);
}
我已尝试通过确定读取是否成功来重新打开端口:

if(!success)
    close(serial_device);
    openPort(); // Same as above
}
但是,实际拔下串行连接器的行为将导致应用程序无法进一步读取任何内容,而select除了超时外将什么也不做。在应用程序运行时重新插入连接器不会解决问题,选择将继续检测不到任何内容

再次成功读取串行端口的唯一方法是重新启动应用程序。我想知道为什么会出现这种情况,以及如何在运行时从被拔掉的串行连接器中恢复。

仅使用一个文件描述符使用
select()
。它还增加了复杂性。
由于串行端口配置为非规范输入,通过正确选择,您可能可以使用更简单的代码一次读取一个字符。例如,尝试
VMIN=1
VTIME=10*超时

然而,正如您所想,如果您愿意处理(或想要)超时而不是等待至少一个字符到达,则
VMIN=0
将使用
select()
模拟原始代码

VMIN=0且VTIME>0
这是一个纯定时读取。如果数据在输入队列中可用,它将被传输到调用者的缓冲区(最多N字节),并立即返回给调用者。否则,驱动程序将阻塞,直到数据到达,或者VTIME十分之一从呼叫开始过期。如果计时器在没有数据的情况下过期,则返回零。单个字节足以满足此读取调用,但如果输入队列中有更多可用字节,则会将其返回给调用方。请注意,这是一个整体计时器,而不是角色间计时器


但是(像OP一样),我很困惑,为什么重新连接端口连接器会中断任何读取或选择监视,而且从未遇到过这样的问题

很难知道问题是主机停止接收还是主板停止发送。带LED指示灯的RS-232诊断加密狗可在此类情况下提供帮助。我注意到您没有检查EOF(
read
返回0)。也许这是个问题?“
成功=失败
”这句话很幽默!这是一个usb rs-232加密狗吗?我知道在原始模式下,EOF永远不应该返回,但我建议进行防御性编程并处理这种情况(至少只是记录错误)。无论出于何种原因,如果EOF在某个较早的时间点(例如,串行电缆断开时立即)交付,它可以解释为什么没有收到进一步的数据。您将
success=false但从不
success=true,因此一旦发生错误,您将永远无法成功。
if(!success)
    close(serial_device);
    openPort(); // Same as above
}