在我的程序中,使用串行端口打开连接,该端口接收具有设定频率(通常为100 Hz)的10字节包。但是我遇到了以下问题:有时(但并非总是)当我关闭连接时,程序会挂起。
在下面的代码中,我没有指定常量;在运行时连接参数(波特率,奇偶校验...)由命令行确定。实际上,通常以波特率230400,无奇偶校验,8位字符大小和1个停止位打开连接。
这就是我打开串口的方式:
struct termios config;
LOGPRINT("Will operate on device \'%s\'\n", pconfig->device);
LOGPRINT("Opening serial device\n");
int flag = O_RDWR | O_NOCTTY | ASYNC_LOW_LATENCY;
// pconfig contains some necessary information to set connection parameters
// async == false for connectin that causes problems
int fd = open(pconfig->device, async? flag | O_NONBLOCK: flag);
if(fd == -1)
{ /* skipped error handling */ }
LOGPRINT("Retrieving terminal attributes\n");
if(!!tcgetattr(fd, &config))
{ /* skipped error handling */ }
else
{
// backup old configuration for restoring it on exit
if(poldconfig != NULL)
memcpy(poldconfig, &config, sizeof(struct termios));
LOGPRINT("Setting terminal attributes\n");
set_attribs(fd, &config, pconfig);
}
...
int set_attribs(const int fd, struct termios* pterm, const struct serial_config* pconfig)
{
// set baud rate
// baud_rates contains integers of actual rates
LOGPRINT("Setting baud rate to %d.\n", baud_rates[pconfig->baud_rate_index]);
// change to raw mode
LOGPRINT("Setting terminal to raw mode\n");
pterm->c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR
| IGNCR | ICRNL | IXON);
pterm->c_oflag &= OPOST;
pterm->c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
// baud_bits contains actual pre-defined baud rate flags
cfsetispeed(pterm, baud_bits[pconfig->baud_rate_index]);
cfsetospeed(pterm, baud_bits[pconfig->baud_rate_index]);
LOGPRINT("Set character size, parity and stop bit flags.\n");
// set character size
pterm->c_cflag &= ~CSIZE;
pterm->c_cflag |= pconfig->csize_flag;
// set parity
pterm->c_cflag &= ~(PARENB | PARODD);
pterm->c_cflag |= pconfig->parity_flag;
// set stopbits
pterm->c_cflag &= ~CSTOPB;
pterm->c_cflag |= pconfig->stopbits_flag;
// enable reading; ignore control lines
pterm->c_cflag |= CREAD | CLOCAL;
LOGPRINT("Flush terminal.\n");
// flush terminal
tcflush(fd, TCIOFLUSH);
LOGPRINT("Apply parameters.\n");
return tcsetattr(fd, TCSANOW, pterm);
}
出于正当理由,我需要强制串行设备驱动程序使用1字节缓冲区来处理传入/传出数据,这是我使用此功能设置的:
int set_port_type(int fd, int ptype)
{
struct serial_struct temp;
int res = ioctl(fd, TIOCGSERIAL, &temp);
if(!!res)
{ /* stipped error handling */ }
temp.type = ptype;
res = ioctl(fd, TIOCSSERIAL, &temp);
if(!!res)
{ /* stipped error handling */ }
return res;
}
ptype = PORT_UNKNOWN或ptype = PORT_16450。
完成串口后,执行以下操作:
它会不时导致程序挂起并停止响应任何外部刺激。它迫使我暂停程序,然后重启系统,因为它永远不会释放它所拥有的文件描述符。
我能做些什么来确保不会发生这种情况?即使设置未恢复,程序也需要自行关闭 - 可能是错误代码。
我正在使用的操作系统是TinyCore Linux。没有其他用户程序与我的程序同时运行。
重要的澄清。我正在使用的串行设备实际上是NPort 5232 - 异步RS-422/485 - 以太网通信器(description from vendor。因此,我使用的串行设备是虚拟的,这使我能够尝试改变它们的类型/大小内部缓冲区。